﻿
&НаКлиенте
Перем ОбъектКонтекст;

&НаКлиенте
Перем ОбъектКонтекстСохраняемый Экспорт;

//&НаКлиенте
//Перем ОбъектКонтекстДляВыполненияСВыбранногоШага;
//&НаКлиенте
//Перем ОбъектКонтекстДляВыполненияСВыбранногоШагаСохраняемый; 
&НаКлиенте
Перем МассивСостоянияКонтекстовДоВыполненияШага;

&НаКлиенте
Перем ТаблицаУжеСуществующихСценариев;

&НаКлиенте
Перем МассивВерсийFeatureИмяФайла;
&НаКлиенте
Перем МассивВерсийFeatureВерсия;

&НаКлиенте
Перем МассивВерсийEPFИмяФайла;
&НаКлиенте
Перем МассивВерсийEPFВерсия;


&НаКлиенте
Перем ИдетОпросЭлементовФормTestClient;
&НаКлиенте
Перем МассивСостояниеФормTestClient;

&НаКлиенте
Перем ОбработкаСвязаннаяСИсполняемойФичей Экспорт;

&НаКлиенте
Перем СлужебнаяПеременная Экспорт;

&НаКлиенте
Перем ТаблицаКонтекстовОбработок;

&НаКлиенте
Перем МассивИменКонтекстовОбработок;

&НаКлиенте
Перем ВыполнятьСценарииАсинхронно;

&НаКлиенте
Перем МассивСценариевДляВыполнения,МассивСтрокДереваДанныеФормы;

&НаКлиенте
Перем ТекИД_СценарияВМассиве;

&НаКлиенте
Перем ТекИД_ШагаВМассиве;

&НаКлиенте
Перем ТекИД_ВыполненногоШагаВМассиве;

&НаКлиенте
Перем СохраненноеСостояниеФормыTestClient;

&НаКлиенте
Перем ВсёЕщёИдётВыполнениеШагов;

&НаКлиенте
Перем МассивИДСтрокиДерева;

&НаКлиенте
Перем МассивРезультатПрохожденияТестовСценария;

&НаКлиенте
Перем ЦветУспешно;
&НаКлиенте
Перем ЦветОжидает;
&НаКлиенте
Перем ЦветНеУспешно;
&НаКлиенте
Перем ЦветЧужойСнипет;

&НаКлиенте
Перем ШагСтрокДляМодуля;

&НаКлиенте
Перем ХостСистема Экспорт;

&НаКлиенте
Перем ИмяФайлаЛогаИнструкцииHTML,ТекущаяФичаИнструкцииHTML;

&НаКлиенте
Перем ИмяФайлаЛогаИнструкцииMarkdown,ТекущаяФичаИнструкцииMarkdown;

&НаКлиенте
Перем СтатусЗапускаСценариев;

&НаКлиенте
Перем ЭтоLinux;

&НаКлиенте
Перем ТаблицаОбработокДляОтладки;

&НаКлиенте
Перем СтрокаШагаСКоторогоНадоВыполнятьСценарий;

&НаКлиенте
Перем СчитываниеМакетаНачСтр Экспорт;
&НаКлиенте
Перем СчитываниеМакетаНачКол Экспорт;
&НаКлиенте
Перем СчитываниеМакетаКолСтр Экспорт;
&НаКлиенте
Перем СчитываниеМакетаКолКол Экспорт;
&НаКлиенте
Перем ПредставлениеВертЧертыВТабДок;



&НаКлиенте
Перем ПрекратитьВыполнениШаговТакКакЗакончилсяСценарий;

&НаКлиенте
Перем МассивPIDОкон1С,ЗначениеПараметровДляСнятияСкриншотов,ТекProcessID;

&НаКлиенте
Перем ИмяФайлаСубтитров,ИнтервалВыполненияШагаПриЗаписиВидео,БылаОшибкаСкриптовСборкиВидео;

&НаКлиенте
Перем СкриншотСделанВСценарии Экспорт;

&НаКлиенте
Перем WshShell;

&НаКлиенте
Перем МассивСнипетовПрерывающихЗаписьСценария,ИДВставкиВВидео,МассивЧастейВидео,КоличествоШаговВДаннойЧастиВидео;

&НаКлиенте
Перем ЭтоЗапускВРежимеКоманднойСтроки,ЭтоЗапускВРежимеБезЗагрукиНастроек;

&НаКлиенте
Перем МассивTTS;



&НаКлиенте
Процедура СделатьСообщение(Знач Сообщение, ТипСообщения = "Информация") Экспорт
	
	ТипСообщения = ?(ТипСообщения = "Информация", СтатусСообщения.Обычное, СтатусСообщения.ОченьВажное);
	Сообщить(Строка(ТекущаяДата()) + " " + Сообщение, ТипСообщения);
	
КонецПроцедуры

&НаКлиенте
Процедура Отладка(Знач Сообщение) Экспорт
	Если Объект.DebugLog Тогда
		СделатьСообщение(Сообщение);
	КонецЕсли; 
КонецПроцедуры

&НаКлиенте
Функция ПолучитьСтрокуВызоваSikuli() Экспорт
	Возврат """C:\Program Files (x86)\Java\jre6\bin\java.exe"" -Xms64M -Xmx512M -Dfile.encoding=UTF-8 -Dpython.path=""C:\Program Files (x86)\Sikuli X\sikuli-script.jar/"" -jar ""C:\Program Files (x86)\Sikuli X\sikuli-ide.jar"" -r ";
КонецФункции	

&НаКлиенте
Процедура Sleep(КолСекунд) Экспорт
	
	Если ЭтоLinux Тогда
		Команда = "ping -i "+Строка(КолСекунд)+" 127.0.0.1 -c 2";
		КомандаСистемы(Команда);
	Иначе
		Команда = "ping 127.0.0.1 -n "+СокрЛП(КолСекунд);
		ВыполнитьКомандуОСБезПоказаЧерногоОкна(Команда);
	КонецЕсли;	
	
КонецПроцедуры

&НаКлиенте
Функция ВыполнитьSikuliСкрипт(СтрокаКоманды,ЖдатьОкончания = -1) Экспорт
	Стр = ПолучитьСтрокуВызоваSikuli() + " " + СтрокаКоманды;
	Возврат ВыполнитьКомандуОСБезПоказаЧерногоОкна(Стр,ЖдатьОкончания);
КонецФункции	

&НаКлиенте
Функция ВыполнитьКомандуОСБезПоказаЧерногоОкна(Стр,ЖдатьОкончания = -1) Экспорт
	//если ЖдатьОкончания = -1, тогда будет ожидания окончания работы приложения
	ИмяВременногоBAT = ПолучитьИмяВременногоФайла("bat");
	
	ЗТ = Новый ЗаписьТекста(ИмяВременногоBAT,КодировкаТекста.ANSI,,Истина); 
	ЗТ.ЗаписатьСтроку(Стр); 
	ЗТ.Закрыть();
	
	Если WshShell = Неопределено Тогда
		WshShell	= Новый COMОбъект("WScript.Shell");
	КонецЕсли;	 
	Рез			= WshShell.Run(ИмяВременногоBAT,0,ЖдатьОкончания);
	WshShell	= Неопределено;
	
	Возврат Рез;
КонецФункции	

&НаКлиенте
Функция СкопироватьСтруктуру(Оригинал)
	Результат = Новый Структура();
	Для каждого Элем Из Оригинал Цикл
		Результат.Вставить(Элем.Ключ,Элем.Значение);
	КонецЦикла;
	
	Возврат Результат;
КонецФункции	

&НаСервереБезКонтекста
Процедура ЗаписатьЛогВЖРПередВыполнениемШагаСервер(ИмяШага)
	ЗаписьЖурналаРегистрации("VanessaBehavior.ПередВыполнениемШага",УровеньЖурналаРегистрации.Информация,,,ИмяШага);
КонецПроцедуры

&НаСервереБезКонтекста
Процедура ЗаписатьЛогВЖРОшибка(ИмяСобытия,Стр)
	ЗаписьЖурналаРегистрации(ИмяСобытия,УровеньЖурналаРегистрации.Ошибка,,,Стр);
КонецПроцедуры

&НаКлиенте
Процедура ЗаписатьЛогВЖРПередВыполнениемШага(ИмяШага)
	ЗаписатьЛогВЖРПередВыполнениемШагаСервер(ИмяШага);
КонецПроцедуры

&НаСервереБезКонтекста
Процедура ЗаписатьЛогВЖРПередВыполнениемСценарияСервер(ИмяСценария)
	ЗаписьЖурналаРегистрации("VanessaBehavior.ПередВыполнениемСценария",УровеньЖурналаРегистрации.Информация,,,ИмяСценария);
КонецПроцедуры

&НаКлиенте
Процедура ЗаписатьЛогВЖРПередВыполнениемСценария(ИмяСценария)
	ЗаписатьЛогВЖРПередВыполнениемСценарияСервер(ИмяСценария);
КонецПроцедуры

&НаКлиенте
Процедура ПосмотретьЗначение(Парам,ПараметрВызватьИсключение = Истина) Экспорт
	Если ПараметрВызватьИсключение Тогда
		Попытка
			ВызватьИсключение "Исключение для просмотра значения.";
		Исключение
		
		КонецПопытки;
	КонецЕсли;  
КонецПроцедуры

&НаСервереБезКонтекста
Функция РазложитьСтрокуВМассивПодстрок(Знач Строка, Знач Разделитель = ",", Знач ПропускатьПустыеСтроки = Неопределено) Экспорт
	
	Результат = Новый Массив;
	
	// для обеспечения обратной совместимости
	Если ПропускатьПустыеСтроки = Неопределено Тогда
		ПропускатьПустыеСтроки = ?(Разделитель = " ", Истина, Ложь);
		Если ПустаяСтрока(Строка) Тогда 
			Если Разделитель = " " Тогда
				Результат.Добавить("");
			КонецЕсли;
			Возврат Результат;
		КонецЕсли;
	КонецЕсли;
		
	Позиция = Найти(Строка, Разделитель);
	Пока Позиция > 0 Цикл
		Подстрока = Лев(Строка, Позиция - 1);
		Если Не ПропускатьПустыеСтроки Или Не ПустаяСтрока(Подстрока) Тогда
			Результат.Добавить(Подстрока);
		КонецЕсли;
		Строка = Сред(Строка, Позиция + СтрДлина(Разделитель));
		Позиция = Найти(Строка, Разделитель);
	КонецЦикла;
	
	Если Не ПропускатьПустыеСтроки Или Не ПустаяСтрока(Строка) Тогда
		Результат.Добавить(Строка);
	КонецЕсли;
	
	Возврат Результат;
	
КонецФункции 

&НаСервереБезКонтекста
Функция УзнатьЕстьПоддержкаНемодальныхФорм()
	СистемнаяИнформация = Новый СистемнаяИнформация;
	Массив1 = РазложитьСтрокуВМассивПодстрок(СистемнаяИнформация.ВерсияПриложения,".");
	Массив2 = РазложитьСтрокуВМассивПодстрок("8.3.3.641",".");
	
	Версия1БольшеИлиРавно = Истина;
	Для Ккк = 0 По Массив1.Количество()-1 Цикл
		Элем1 = Массив1.Получить(Ккк);
		Элем2 = Массив2.Получить(Ккк);
		
		Если Число(Элем2) > Число(Элем1) Тогда
			Версия1БольшеИлиРавно = Ложь;
		КонецЕсли;	 
	КонецЦикла;
	
	Возврат Версия1БольшеИлиРавно;
КонецФункции

&НаСервере
Функция УзнатьЕстьПоддержкаАсинхронныхВызовов()
	СистемнаяИнформация = Новый СистемнаяИнформация;
	Массив1 = РазложитьСтрокуВМассивПодстрок(СистемнаяИнформация.ВерсияПриложения,".");
	Массив2 = РазложитьСтрокуВМассивПодстрок("8.3.5.1383",".");
	
	Версия1БольшеИлиРавно = Истина;
	Для Ккк = 0 По Массив1.Количество()-1 Цикл
		Элем1 = Массив1.Получить(Ккк);
		Элем2 = Массив2.Получить(Ккк);
		
		Если Число(Элем2) > Число(Элем1) Тогда
			Версия1БольшеИлиРавно = Ложь;
		КонецЕсли;	 
	КонецЦикла;
	
	Рез = Версия1БольшеИлиРавно И Вычислить("Метаданные.РежимИспользованияСинхронныхВызововРасширенийИВнешнихКомпонент <> Метаданные.СвойстваОбъектов.РежимИспользованияСинхронныхВызововРасширенийИВнешнихКомпонент.Использовать");
	
	Возврат Рез;
КонецФункции

&НаКлиенте
Функция УзнатьЕстьПоддержкаНемодальныхФормКлиент() Экспорт
	Возврат УзнатьЕстьПоддержкаНемодальныхФорм();
КонецФункции

&НаКлиенте
Процедура ОбновитьКнопкуЗагрузитьФичи()
	Если Объект.текЗначениеОперации = "ЗагрузитьФичиИзКаталога" Тогда
		Элементы.ПодменюЗагрузитьФичи.Заголовок = "Загрузить фичи из каталога";
	ИначеЕсли Объект.текЗначениеОперации = "ЗагрузитьОднуФичу" Тогда
		Элементы.ПодменюЗагрузитьФичи.Заголовок = "Загрузить одну фичу";
	ИначеЕсли Объект.текЗначениеОперации = "" Тогда
	Иначе	
		Стр = "Ошибка! Неизвестное значение параметра текЗначениеОперации = " + Объект.текЗначениеОперации;
		Сообщить(Стр);	
		ВызватьИсключение Стр;
	КонецЕсли;	 
КонецПроцедуры

&НаКлиенте
Процедура ЗагрузитьТестыЗагрузитьФичиИзКаталога()
	ОчиститьСообщения();
	
	Режим = РежимДиалогаВыбораФайла.ВыборКаталога;
	ДиалогОткрытияФайла = Новый ДиалогВыбораФайла(Режим);
	Если ЕстьПоддержкаАсинхронныхВызовов Тогда
		ОписаниеОповещения = Вычислить("Новый ОписаниеОповещения(""ОбработатьВыборФайла"", ЭтаФорма)");
		Выполнить("ДиалогОткрытияФайла.Показать(ОписаниеОповещения)");
	Иначе	
		Если ДиалогОткрытияФайла.Выбрать() Тогда
			Объект.КаталогФич = ДиалогОткрытияФайла.Каталог;
			ЗагрузитьФичи();
		Иначе
			Возврат;
		КонецЕсли;
	КонецЕсли;
	
КонецПроцедуры

&НаКлиенте
Процедура ЗагрузитьФичиИзКаталога(Команда)
	Объект.текЗначениеОперации = "ЗагрузитьФичиИзКаталога";
	ОбновитьКнопкуЗагрузитьФичи();
	
	Объект.РежимВыполненияСценарияСВыбранногоШага = Ложь;
	СтрокаШагаСКоторогоНадоВыполнятьСценарий      = Неопределено;
	МассивСостоянияКонтекстовДоВыполненияШага     = Новый Массив;
	
	ЗагрузитьТестыЗагрузитьФичиИзКаталога();
КонецПроцедуры

&НаСервере
Функция ПолучитьПутьКОбработкеСервер()
	Объект1 = РеквизитФормыВЗначение("Объект");
	Возврат Объект1.ИспользуемоеИмяФайла;
КонецФункции

&НаКлиенте
Процедура ВосстановитьНастройкиКлиент()
	Если Объект.РежимСамотестирования Тогда
		Возврат;
	КонецЕсли;  
	
	//СтрЗапуска = "StartFeaturePlayer;VBParams=H:\Commons\Temp\VBParams.json";
	СтрЗапуска = СокрЛП(ПараметрЗапуска);
	Если СтрЗапуска <> "" Тогда
		СтруктураПараметров = ПолучитьСтруктуруПараметров(СтрЗапуска);
		StartFeaturePlayer = ПолучитьЗначениеПереданногоПараметра(СтруктураПараметров,"StartFeaturePlayer");
		Если StartFeaturePlayer = Истина Тогда
			ЭтоЗапускВРежимеКоманднойСтроки = Истина;
			//значит мы в режиме ЗапускВРежимеКоманднойСтроки
			Возврат;
		КонецЕсли;	
		
		NoLoadConfig = ПолучитьЗначениеПереданногоПараметра(СтруктураПараметров,"NoLoadConfig");
		Если NoLoadConfig = Истина Тогда
			ЭтоЗапускВРежимеКоманднойСтроки    = Истина;
			ЭтоЗапускВРежимеБезЗагрукиНастроек = Истина;
			//значит нам сообщили, что не надо загружать настройки
			Возврат;
		КонецЕсли;	
	КонецЕсли;	
	
	
	ВосстановитьНастройки(ЭтоLinux);
КонецПроцедуры

&НаСервере
Процедура ВосстановитьНастройки(ЭтоLinux)
	
	Настройки = ХранилищеОбщихНастроек.Загрузить("VanessaBehaviorUF");
	Если ТипЗнч(Настройки) = Тип("Структура") Тогда
		
		Настройки.Свойство("DebugLog", Объект.DebugLog);
		Настройки.Свойство("ГенерироватьУФ",Объект.ГенерироватьУФ);
		Настройки.Свойство("КаталогФич", Объект.КаталогФич);
		Настройки.Свойство("ДелатьОтчетВФорматеАллюр", Объект.ДелатьОтчетВФорматеАллюр);
		Настройки.Свойство("КаталогOutputAllure", Объект.КаталогOutputAllure);
		Настройки.Свойство("ДелатьОтчетВоВнутреннемФормате", Объект.ДелатьОтчетВоВнутреннемФормате);
		Настройки.Свойство("ДелатьОтчетВФорматеxUnit", Объект.ДелатьОтчетВФорматеxUnit);
		Настройки.Свойство("КаталогOutputxUnit", Объект.КаталогOutputxUnit);
		Настройки.Свойство("текЗначениеОперации", Объект.текЗначениеОперации);
		Настройки.Свойство("КаталогиБиблиотек", Объект.КаталогиБиблиотек);
		Настройки.Свойство("СоздаватьИнструкциюHTML", Объект.СоздаватьИнструкциюHTML);
		Настройки.Свойство("КаталогOutputИнструкцияHTML", Объект.КаталогOutputИнструкцияHTML);
		
		Настройки.Свойство("СоздаватьИнструкциюMarkdown", Объект.СоздаватьИнструкциюMarkdown);
		Настройки.Свойство("КаталогOutputИнструкцияMarkdown", Объект.КаталогOutputИнструкцияMarkdown);
		
		Настройки.Свойство("СоздаватьИнструкциюВидео", Объект.СоздаватьИнструкциюВидео);
		Настройки.Свойство("КаталогOutputИнструкцияВидео", Объект.КаталогOutputИнструкцияВидео);
		Настройки.Свойство("КаталогСкриптовСборкиВидео", Объект.КаталогСкриптовСборкиВидео);
		
		Настройки.Свойство("СоздаватьЗакоментированныйКодДляПереиспользуемыхПроцедур", Объект.СоздаватьЗакоментированныйКодДляПереиспользуемыхПроцедур);
		Настройки.Свойство("СписокТеговИсключение", Объект.СписокТеговИсключение);
		Настройки.Свойство("СписокТеговОтбор", Объект.СписокТеговОтбор);
		Настройки.Свойство("ДелатьЛогВыполненияСценариевВЖР", Объект.ДелатьЛогВыполненияСценариевВЖР);
		Настройки.Свойство("ПодключитьВнешниеОбработкиДляОтладки", Объект.ПодключитьВнешниеОбработкиДляОтладки);
		Настройки.Свойство("СоздаватьОбластиПриГенерацииКода", Объект.СоздаватьОбластиПриГенерацииКода);
		
		Если НЕ Настройки.Свойство("СоздаватьОбластиПриГенерацииКода") Тогда
			Объект.СоздаватьОбластиПриГенерацииКода = Истина;
		КонецЕсли;	 
		
		Если Настройки.Свойство("ВыполнятьШагиАссинхронно") Тогда
			Настройки.Свойство("ВыполнятьШагиАссинхронно", Объект.ВыполнятьШагиАссинхронно);
		КонецЕсли;	
		
		Если Настройки.Свойство("СохранятьКонтекстыПередВыполнениемШагов") Тогда
			Настройки.Свойство("СохранятьКонтекстыПередВыполнениемШагов", Объект.СохранятьКонтекстыПередВыполнениемШагов);
		КонецЕсли;	
		
		Настройки.Свойство("ВыводитьТекстМодуляВместоПерегенерацииEPF", Объект.ВыводитьТекстМодуляВместоПерегенерацииEPF);
		
		Если Настройки.Свойство("КомандаСделатьСкриншот") Тогда
			Настройки.Свойство("КомандаСделатьСкриншот", Объект.КомандаСделатьСкриншот);
		Иначе
			Если ЭтоLinux Тогда
				Объект.КомандаСделатьСкриншот = "import -window root";
			Иначе
				Объект.КомандаСделатьСкриншот = """C:\Program Files (x86)\IrfanView\i_view32.exe"" /capture=1 /convert=";
			КонецЕсли;	 
		КонецЕсли;	 
		
		
		Настройки.Свойство("ДелатьСкриншотПриВозникновенииОшибки", Объект.ДелатьСкриншотПриВозникновенииОшибки);
		Настройки.Свойство("КаталогOutputСкриншоты", Объект.КаталогOutputСкриншоты);
		
		Настройки.Свойство("ИнтервалВыполненияШагаЗаданныйПользователем", Объект.ИнтервалВыполненияШагаЗаданныйПользователем);
	Иначе	
		Объект.ГенерироватьУФ = Истина;
		Если СокрЛП(Объект.КаталогИнструментов) <> "" Тогда
			Объект.КаталогиБиблиотек.Добавить(Объект.КаталогИнструментов + "\features\Libraries");
			Объект.СписокТеговИсключение.Добавить("IgnoreOnCIMainBuild");
		КонецЕсли;	 
		
		Если ЭтоLinux Тогда
			Объект.КомандаСделатьСкриншот = "import -window root";
		Иначе
			Объект.КомандаСделатьСкриншот = """C:\Program Files (x86)\IrfanView\i_view32.exe"" /capture=1 /convert=";
		КонецЕсли;	 
	КонецЕсли;

КонецПроцедуры

&НаСервере
Процедура СохранитьНастройки()
	Если Объект.РежимСамотестирования Тогда
		Возврат;
	КонецЕсли;  
	
	Настройки = Новый Структура;
	Настройки.Вставить("DebugLog", Объект.DebugLog);
	//Настройки.Вставить("GenerateEpf", Объект.GenerateEpf);
	//Настройки.Вставить("TestRun", Объект.TestRun);
	Настройки.Вставить("ГенерироватьУФ", Объект.ГенерироватьУФ);
	//Настройки.Вставить("КаталогИнструментов", Объект.КаталогИнструментов);
	Настройки.Вставить("КаталогФич", Объект.КаталогФич);
	
	Настройки.Вставить("ДелатьОтчетВФорматеАллюр", Объект.ДелатьОтчетВФорматеАллюр);
	Настройки.Вставить("КаталогOutputAllure", Объект.КаталогOutputAllure);
	
	Настройки.Вставить("ДелатьОтчетВоВнутреннемФормате", Объект.ДелатьОтчетВоВнутреннемФормате);
	
	Настройки.Вставить("ДелатьОтчетВФорматеxUnit", Объект.ДелатьОтчетВФорматеxUnit);
	Настройки.Вставить("КаталогOutputxUnit", Объект.КаталогOutputxUnit);
	
	Настройки.Вставить("текЗначениеОперации", Объект.текЗначениеОперации);
	Настройки.Вставить("КаталогиБиблиотек", Объект.КаталогиБиблиотек);
	
	Настройки.Вставить("СоздаватьИнструкциюHTML", Объект.СоздаватьИнструкциюHTML);
	Настройки.Вставить("КаталогOutputИнструкцияHTML", Объект.КаталогOutputИнструкцияHTML);
	
	Настройки.Вставить("СоздаватьИнструкциюMarkdown", Объект.СоздаватьИнструкциюMarkdown);
	Настройки.Вставить("КаталогOutputИнструкцияMarkdown", Объект.КаталогOutputИнструкцияMarkdown);
	
	Настройки.Вставить("СоздаватьИнструкциюВидео", Объект.СоздаватьИнструкциюВидео);
	Настройки.Вставить("КаталогOutputИнструкцияВидео", Объект.КаталогOutputИнструкцияВидео);
	Настройки.Вставить("КаталогСкриптовСборкиВидео", Объект.КаталогСкриптовСборкиВидео);
	
	Настройки.Вставить("СоздаватьЗакоментированныйКодДляПереиспользуемыхПроцедур", Объект.СоздаватьЗакоментированныйКодДляПереиспользуемыхПроцедур);
	
	Настройки.Вставить("СписокТеговИсключение", Объект.СписокТеговИсключение);
	Настройки.Вставить("СписокТеговОтбор", Объект.СписокТеговОтбор);
	
	Настройки.Вставить("ДелатьЛогВыполненияСценариевВЖР", Объект.ДелатьЛогВыполненияСценариевВЖР);
	Настройки.Вставить("ПодключитьВнешниеОбработкиДляОтладки", Объект.ПодключитьВнешниеОбработкиДляОтладки);
	
	Настройки.Вставить("ВыполнятьШагиАссинхронно", Объект.ВыполнятьШагиАссинхронно);
	
	Настройки.Вставить("СохранятьКонтекстыПередВыполнениемШагов", Объект.СохранятьКонтекстыПередВыполнениемШагов);
	
	Настройки.Вставить("СоздаватьОбластиПриГенерацииКода", Объект.СоздаватьОбластиПриГенерацииКода);
	
	
	Настройки.Вставить("КаталогИнструментов", Объект.КаталогИнструментов);
	
	Настройки.Вставить("ВыводитьТекстМодуляВместоПерегенерацииEPF", Объект.ВыводитьТекстМодуляВместоПерегенерацииEPF);
	
	Настройки.Вставить("КомандаСделатьСкриншот", Объект.КомандаСделатьСкриншот);
	
	Настройки.Вставить("ДелатьСкриншотПриВозникновенииОшибки", Объект.ДелатьСкриншотПриВозникновенииОшибки);
	Настройки.Вставить("КаталогOutputСкриншоты", Объект.КаталогOutputСкриншоты);
	
	Настройки.Вставить("ИнтервалВыполненияШагаЗаданныйПользователем", Объект.ИнтервалВыполненияШагаЗаданныйПользователем);
	
	ХранилищеОбщихНастроек.Сохранить("VanessaBehaviorUF",, Настройки);
КонецПроцедуры

&НаСервере
Функция ПодключитьВнешнююОбработкуСервер(АдресХранилища)
	Возврат ВнешниеОбработки.Подключить(АдресХранилища,,Ложь); 
КонецФункции 

&НаКлиенте
Процедура ОбработкаПослеПомещенияФайла(Результат,АдресХранилища,ВыбранноеИмяФайла,ДополнительныеПараметры) Экспорт
	ИмяОбработки = ПодключитьВнешнююОбработкуСервер(АдресХранилища);
	ДополнительныеПараметры.Вставить("ИмяОбработки",ИмяОбработки);
КонецПроцедуры

&НаКлиенте
Функция ПодключитьВнешнююОбработкуКлиент(ИмяФайла) Экспорт
	Попытка
		ДополнительныеПараметры = Новый Структура;
		Если ЕстьПоддержкаНемодальныхФорм Тогда
			Оповещение = Вычислить("Новый ОписаниеОповещения(""ОбработкаПослеПомещенияФайла"", ЭтаФорма, ДополнительныеПараметры)");
			Выполнить("НачатьПомещениеФайла(Оповещение,, ИмяФайла, Ложь, УникальныйИдентификатор);");
			
			Возврат ДополнительныеПараметры.ИмяОбработки;
		Иначе
			АдресХранилища = "";
			ПоместитьФайл(АдресХранилища, ИмяФайла, , Ложь, УникальныйИдентификатор);
			//ПодключитьВнешнююОбработку(АдресХранилища);
			Результат = Неопределено;
			ИмяОбработки = ПодключитьВнешнююОбработкуСервер(АдресХранилища);
			Возврат ИмяОбработки;
		КонецЕсли;
	
	Исключение
		Возврат Неопределено;
	КонецПопытки;
КонецФункции 

&НаКлиенте
Процедура ПодключитьИнструментПарсерФич()
	ПутьКФайлу = Объект.КаталогИнструментов + "/vbFeatureReader.epf";
	Файл = Новый Файл(ПутьКФайлу);
	Если Не Файл.Существует() Тогда
		СделатьСообщение("Файл " + ПутьКФайлу + " не найден!");
		ВызватьИсключение "Не найден файл vbFeatureReader.epf!";
	КонецЕсли;	 
	
	Результат = ПодключитьВнешнююОбработкуКлиент(Файл.ПолноеИмя);
КонецПроцедуры

&НаСервере
Процедура ДобавитьСнипет(Знач ID,Знач СтрокаРеальнойПроцедуры,Знач ИмяФайла,БылиОшибки,ТзнТаблицаИзвестныхStepDefinition)
	
	
	СтрокаРеальнойПроцедуры = СокрЛП(СтрокаРеальнойПроцедуры);
	ID                      = СокрЛП(ID);
	
	//уберем слово "Экспорт"
	Если Прав(НРег(СтрокаРеальнойПроцедуры),7) = "экспорт" Тогда
		СтрокаРеальнойПроцедуры = Лев(СтрокаРеальнойПроцедуры,СтрДлина(СтрокаРеальнойПроцедуры)-7);
		СтрокаРеальнойПроцедуры = СокрЛП(СтрокаРеальнойПроцедуры);
	КонецЕсли;
	
	Если Лев(НРег(СтрокаРеальнойПроцедуры),9) = "процедура" Тогда
		СтрокаРеальнойПроцедуры = СокрЛП(Сред(СтрокаРеальнойПроцедуры,10));
	КонецЕсли;
	
	Поз = Найти(ID,"(");
	СтрПараметры = Сред(ID,Поз+1);
	СтрПараметры = Лев(СтрПараметры,СтрДлина(СтрПараметры)-1);
	
	МассивПром = РазложитьСтрокуВМассивПодстрок(СтрПараметры, ",");
	МассивПараметров = Новый Массив;
	Для Каждого Элем Из МассивПром Цикл
		СтруктураПарам = Новый Структура;
		Тип = "Строка";
		Если Найти(НРег(Элем),"число") > 0 Тогда
			Тип = "Число";
		КонецЕсли;
		Если Найти(НРег(Элем),"дата") > 0 Тогда
			Тип = "Дата";
		КонецЕсли;
		СтруктураПарам.Вставить("Тип",Тип);
		МассивПараметров.Добавить(СтруктураПарам);
	КонецЦикла;
	
	ПромСтр = ТзнТаблицаИзвестныхStepDefinition.Найти(ID,"ID");
	Если ПромСтр <> Неопределено Тогда
		Если НРег(ПромСтр.ИмяФайла) = НРег(ИмяФайла) Тогда //значит этот снипет из того же файла
			Возврат;
		КонецЕсли;	
	КонецЕсли;	 
	Если ПромСтр <> Неопределено Тогда
		БылиОшибки = Истина;
		Сообщить("Ошибка в файле " + ИмяФайла + ", снипет " + ID + " уже был в " + ПромСтр.ИмяФайла);
		Возврат;
	КонецЕсли;
	
	СтрТаблицаИзвестныхStepDefinition                         = ТзнТаблицаИзвестныхStepDefinition.Добавить();
	СтрТаблицаИзвестныхStepDefinition.ID                      = ID;
	СтрТаблицаИзвестныхStepDefinition.СтрокаРеальнойПроцедуры = СтрокаРеальнойПроцедуры;
	СтрТаблицаИзвестныхStepDefinition.ИмяФайла                = ИмяФайла;
	СтрТаблицаИзвестныхStepDefinition.Параметры               = МассивПараметров;
	
	
КонецПроцедуры

&НаСервере
Процедура ДобавитьСнипетыСервер(МассивСнипетовИзОбработки,ИмяФайла,БылиОшибки)
	ТзнТаблицаИзвестныхStepDefinition = РеквизитФормыВЗначение("ТаблицаИзвестныхStepDefinition");
	
	Для каждого Снипет Из МассивСнипетовИзОбработки Цикл
		ДобавитьСнипет(Снипет.Снипет,Снипет.ИмяПроцедуры,ИмяФайла,БылиОшибки,ТзнТаблицаИзвестныхStepDefinition);
	КонецЦикла;
	
	ЗначениеВРеквизитФормы(ТзнТаблицаИзвестныхStepDefinition,"ТаблицаИзвестныхStepDefinition");
	
КонецПроцедуры

&НаСервере
Процедура УдалитьИзТаблицаИзвестныхStepDefinitionДанныеПоФайлуСервер(ИмяФайла)
	ТзнТаблицаИзвестныхStepDefinition = РеквизитФормыВЗначение("ТаблицаИзвестныхStepDefinition");
	
	Отбор = Новый Структура;
	Отбор.Вставить("ИмяФайла",ИмяФайла);
	МассивСтрок = ТзнТаблицаИзвестныхStepDefinition.НайтиСтроки(Отбор);
	
	Для каждого СтрокаТаблицы Из МассивСтрок Цикл
		ТзнТаблицаИзвестныхStepDefinition.Удалить(СтрокаТаблицы);
	КонецЦикла;
	
	ЗначениеВРеквизитФормы(ТзнТаблицаИзвестныхStepDefinition,"ТаблицаИзвестныхStepDefinition");
КонецПроцедуры

&НаКлиенте
Процедура ПолучитьУжеСуществующиеСнипетыИзОбработок(Знач КаталогФич,ДополнительныеПараметры = Неопределено)
	Файл = Новый Файл(КаталогФич);
	
	БылиОшибки = Ложь;
	НачальныйКаталог = КаталогФич;
	КаталогПоиска    = НачальныйКаталог;
	
	Файл = Новый Файл(НачальныйКаталог);
	Если НРег(Файл.Расширение) = ".feature" Тогда
		КаталогПоиска = Файл.Путь;
	КонецЕсли;	 
	
	Отладка("Ищу снипеты в каталоге " + КаталогПоиска);
	
	Если ЕстьПоддержкаАсинхронныхВызовов Тогда
		МассивФайлов = ПолучитьЗначениеПоРанееСобраннойИнформации(ДополнительныеПараметры,КаталогФич,"НайденныеФайлы"); //это файлы по данной библиотеке
		Если МассивФайлов = Неопределено Тогда
			МассивФайлов = ПолучитьЗначениеПоРанееСобраннойИнформации(ДополнительныеПараметры,"ПоискEPF","НайденныеФайлы");
		КонецЕсли;	 
	Иначе	
		МассивФайлов = НайтиФайлы(КаталогПоиска,"*.epf",Истина);
	КонецЕсли;	 
	
	Для Каждого Файл Из МассивФайлов Цикл
	
		Если НЕ ЕстьПоддержкаАсинхронныхВызовов Тогда
			
			ВерсияФайла = Файл.ПолучитьВремяИзменения();
			ИДВерсииEPF = МассивВерсийEPFИмяФайла.Найти(Файл.ПолноеИмя);
			Если ИДВерсииEPF = Неопределено Тогда
				МассивВерсийEPFИмяФайла.Добавить(Файл.ПолноеИмя);
				МассивВерсийEPFВерсия.Добавить(ВерсияФайла);
			Иначе	
				Если МассивВерсийEPFВерсия[ИДВерсииEPF] <> ВерсияФайла Тогда
					//значит файл изменился
					//обновляем версию и удаляем старые снипеты
					МассивВерсийEPFВерсия[ИДВерсииEPF] = ВерсияФайла;
					
					УдалитьИзТаблицаИзвестныхStepDefinitionДанныеПоФайлуСервер(Файл.ПолноеИмя);
					
					ИДМассивИменКонтекстовОбработок = МассивИменКонтекстовОбработок.Найти(Файл.ПолноеИмя);
					МассивИменКонтекстовОбработок.Удалить(ИДМассивИменКонтекстовОбработок);
					ТаблицаКонтекстовОбработок.Удалить(ИДМассивИменКонтекстовОбработок);
					
					Отладка("Загрузил новую версию: " + Файл.ПолноеИмя);
					
				Иначе
					//значит уже актуальная версия файла загружена
					//Сообщить("!!!!!!!!!!!!!!!!!!! " + Файл.ПолноеИмя);
					Продолжить;
				КонецЕсли; 
			КонецЕсли; 
		КонецЕсли; 
		
		Попытка
			ИмяОбработки = ПодключитьВнешнююОбработкуКлиент(Файл.ПолноеИмя);
			ФормаОбработки = ПолучитьФорму("ВнешняяОбработка." + ИмяОбработки + ".Форма.Форма");
			Если ФормаОбработки = Неопределено Тогда
				Продолжить;
			КонецЕсли; 
		Исключение
			Отладка("Не смог получить список шагов в обработке: " + Файл.ПолноеИмя);
			Отладка("" + ОписаниеОшибки());
			Продолжить;
		КонецПопытки;
		
		Попытка
			МассивСнипетовИзОбработки = ФормаОбработки.ПолучитьСписокТестов(ЭтаФорма);
		Исключение
			Сообщить("Не смог загрузить снипеты из " + Файл.ПолноеИмя);
			Сообщить(ОписаниеОшибки());
			Продолжить;
		КонецПопытки;
		
		
		
		СтрТаблицаКонтекстовОбработок = Новый Структура;
		СтрТаблицаКонтекстовОбработок.Вставить("ИмяФайла",Файл.ПолноеИмя);
		СтрТаблицаКонтекстовОбработок.Вставить("Обработка",ФормаОбработки);
		
		ТаблицаКонтекстовОбработок.Добавить(СтрТаблицаКонтекстовОбработок);
		МассивИменКонтекстовОбработок.Добавить(Файл.ПолноеИмя);
		
		ДобавитьСнипетыСервер(МассивСнипетовИзОбработки,Файл.ПолноеИмя,БылиОшибки);
		
	КонецЦикла;
	
	Если БылиОшибки Тогда
		Сообщить("Были ошибки в ПросканироватьИсходникиИНайтиВсеStepDefinition.");
	КонецЕсли;
	
КонецПроцедуры

&НаКлиенте
Функция ОбходКаталогов(ПутьКаталога,МассивРезультатОбходаКаталогов,Уровень,ДополнительныеПараметры,ТекРодитель,КолЭлементовДобавлено)
	
	Если ЕстьПоддержкаАсинхронныхВызовов Тогда
		ФайлПутьКаталога = Новый Файл(ПутьКаталога);
		Если ФайлПутьКаталога.Расширение = ".feature" Тогда
			НайденныеФайлы = Новый Массив;//вернём одну фичу
			НайденныеФайлы.Добавить(ФайлПутьКаталога);
			ТекРодитель = НайденныеФайлы[0].Путь;
		Иначе	
			НайденныеФайлы = ПолучитьЗначениеПоРанееСобраннойИнформации(ДополнительныеПараметры,"ПоискFeature","НайденныеФайлы");
			Если ТекРодитель = Неопределено Тогда
				Если НайденныеФайлы.Количество() > 0 Тогда
					ТекРодитель = НайденныеФайлы[0].Путь;
				КонецЕсли;	 
			КонецЕсли;	 
		КонецЕсли;	 
		
	Иначе	
		ФайлПутьКаталога = Новый Файл(ПутьКаталога);
		Если ФайлПутьКаталога.ЭтоКаталог() Тогда
			НайденныеФайлы = НайтиФайлы(ПутьКаталога,"*");
		Иначе
			НайденныеФайлы = Новый Массив;//вернём одну фичу
			НайденныеФайлы.Добавить(ФайлПутьКаталога);
		КонецЕсли;	 
	КонецЕсли;	 
		
	Для каждого ф из НайденныеФайлы цикл
		Если ЕстьПоддержкаАсинхронныхВызовов Тогда
			Если ф.Путь <> ТекРодитель Тогда
				Продолжить;
			КонецЕсли;	 
		КонецЕсли;  
		
		Если Не ЕстьПоддержкаАсинхронныхВызовов Тогда
			ЭтоКаталог = ф.ЭтоКаталог();
		Иначе
			ЭтоКаталог = Ложь;
			Если ф.Расширение = "" Тогда
				ЭтоКаталог = Истина;
			КонецЕсли;	 
		КонецЕсли;	 
		
		Если ЭтоКаталог тогда //это каталог
			СтруткураФайла = Новый Структура;
			СтруткураФайла.Вставить("Уровень",Уровень);
			СтруткураФайла.Вставить("Каталог",Истина);
			СтруткураФайла.Вставить("Фича",Ложь);
			СтруткураФайла.Вставить("Имя",ф.Имя);
			СтруткураФайла.Вставить("ПолныйПуть",ф.ПолноеИмя);
			МассивРезультатОбходаКаталогов.Добавить(СтруткураФайла);
			ТекИД = МассивРезультатОбходаКаталогов.Количество()-1;
			
			ТекКолЭлементовДобавлено = 0;
			Уровень = Уровень + 1;
			ОбходКаталогов(ДополнитьСлешВПуть(ПутьКаталога)+ф.Имя,МассивРезультатОбходаКаталогов,Уровень,ДополнительныеПараметры,ДополнитьСлешВПуть(ф.ПолноеИмя), ТекКолЭлементовДобавлено);
			Уровень = Уровень - 1;
			
			Если ТекКолЭлементовДобавлено = 0 Тогда
				МассивРезультатОбходаКаталогов.Удалить(ТекИД);
			КонецЕсли;  
			КолЭлементовДобавлено = КолЭлементовДобавлено + ТекКолЭлементовДобавлено;
			
		ИначеЕсли НРег(ф.Расширение) = ".feature" Тогда
			
			ДвоичныеДанные = Новый ДвоичныеДанные(ф.ПолноеИмя);
			СтруткураФайла = ПолучитьСтруткураФайлаФичи(Уровень,ф.ИмяБезРасширения,ф.ПолноеИмя,ДвоичныеДанные);
			
			МассивРезультатОбходаКаталогов.Добавить(СтруткураФайла);
			КолЭлементовДобавлено = КолЭлементовДобавлено + 1;
			
		КонецЕсли;
		
	КонецЦикла;
	
КонецФункции

&НаКлиенте
Функция ПолучитьСтруткураФайлаФичи(Уровень,ИмяБезРасширения,ПолноеИмя,ДвоичныеДанные)
	СтруткураФайла = Новый Структура;
	СтруткураФайла.Вставить("Уровень",Уровень);
	СтруткураФайла.Вставить("Каталог",Ложь);
	СтруткураФайла.Вставить("Фича",Истина);
	СтруткураФайла.Вставить("Имя",ИмяБезРасширения);
	СтруткураФайла.Вставить("ПолныйПуть",ПолноеИмя);
	СтруткураФайла.Вставить("ДвоичныеДанные",ДвоичныеДанные);
	
	Возврат СтруткураФайла;
КонецФункции	

&НаСервере
Процедура УдалитьПустыеКаталогиИзДерева(Дерево)
	КолСтрок = Дерево.Строки.Количество();
	Для Ккк = 0 По КолСтрок-1 Цикл
		Строка = Дерево.Строки[КолСтрок-1 - Ккк];
		Если Строка.Каталог Тогда
			Если Строка.Строки.Количество() = 0 Тогда
				Дерево.Строки.Удалить(Строка);
			Иначе	
				УдалитьПустыеКаталогиИзДерева(Строка);
			КонецЕсли;  
		КонецЕсли;  
	КонецЦикла;
КонецПроцедуры


&НаСервере
Функция ПреобразоватьМассивТаблицаУжеСуществующихСценариевВТаблицуЗначений(ИсходныйМассив)
	Тзн = Новый ТаблицаЗначений;
	Тзн.Колонки.Добавить("ИмяСценария");
	Тзн.Колонки.Добавить("ИмяФайла");
	Тзн.Колонки.Добавить("ТаблицаШагов");
	Тзн.Колонки.Добавить("ДвоичныеДанные");
	Для каждого Элем Из ИсходныйМассив Цикл
		СтрТзн = Тзн.Добавить();
		
		СтрТзн.ИмяСценария    = Элем.ИмяСценария;
		СтрТзн.ИмяФайла       = Элем.ИмяФайла;
		СтрТзн.ТаблицаШагов   = Элем.ТаблицаШагов;
		СтрТзн.ДвоичныеДанные = Элем.ДвоичныеДанные;
	КонецЦикла;
	
	Возврат Тзн;
КонецФункции	

&НаСервере
Процедура УдалитьПустыеКаталоги(МассивКаталоговДляПроверкиНаПустоту)
	Массив = Новый Массив;
	
	Для каждого ВеткаСтроки Из МассивКаталоговДляПроверкиНаПустоту Цикл
		Если ВеткаСтроки.Количество() = 0 Тогда
			ВеткаРодитель = ВеткаСтроки.Родитель.Родитель;//так определяется родитель на один уровень вверх, когда в переменной лежат строки дерева
			Если ВеткаРодитель = Неопределено Тогда
				Продолжить;
			КонецЕсли;	 
			
			Если Массив.Найти(ВеткаРодитель) = Неопределено Тогда
				Массив.Добавить(ВеткаРодитель.Строки);
			КонецЕсли;	 
			
			ВеткаРодитель.Строки.Удалить(ВеткаСтроки.Родитель);
		КонецЕсли;	 
	КонецЦикла;
	
	Если Массив.Количество() > 0 Тогда
		УдалитьПустыеКаталоги(Массив);
	КонецЕсли;	 
КонецПроцедуры

&НаСервере
Процедура ЗаполнитьСтрокиДереваФичамиСервер(Дерево,FeatureReader,ТзнТаблицаИзвестныхStepDefinition,СтруктураПараметров)
	
	
	МассивСтрокДляУдаления = Новый Массив;
	Для каждого Строка Из Дерево.Строки Цикл
		Если Строка.Фича Тогда
			СтруктураПараметров.Вставить("УдалитьСтрокуФичиИзДерева",Ложь);
			
			//Сообщить("ЗаполнитьСтрокиДереваФичамиСервер. " + Строка.ПолныйПуть);
			
			
			FeatureReader.ЗагрузитьФичу(Строка.ПолныйПуть,Строка.Строки,ТзнТаблицаИзвестныхStepDefinition,СтруктураПараметров);
			
			Если СтруктураПараметров.УдалитьСтрокуФичиИзДерева Тогда
				СтуктураРодительПотомок = Новый Структура;
				СтуктураРодительПотомок.Вставить("СтрокиГдеНаходитсяФича",Дерево.Строки);
				СтуктураРодительПотомок.Вставить("СтрокаФичи",Строка);
				МассивСтрокДляУдаления.Добавить(СтуктураРодительПотомок);
			КонецЕсли;	 
		Иначе	
			ЗаполнитьСтрокиДереваФичамиСервер(Строка,FeatureReader,ТзнТаблицаИзвестныхStepDefinition,СтруктураПараметров);
		КонецЕсли;  
	КонецЦикла;
	
	
	МассивКаталоговДляПроверкиНаПустоту = СтруктураПараметров.МассивКаталоговДляПроверкиНаПустоту;
	Для каждого Элем Из МассивСтрокДляУдаления Цикл
		Элем.СтрокиГдеНаходитсяФича.Удалить(Элем.СтрокаФичи);
		
		Если МассивКаталоговДляПроверкиНаПустоту.Найти(Элем.СтрокиГдеНаходитсяФича) = Неопределено Тогда
			МассивКаталоговДляПроверкиНаПустоту.Добавить(Элем.СтрокиГдеНаходитсяФича);
		КонецЕсли;	 
	КонецЦикла;
	
КонецПроцедуры

&НаСервере
Процедура ЗаполнитьДеревоЗначенийПоМассивуСервер(МассивРезультатОбходаКаталогов,ДвДанныеvbFeatureReader,СтруктураПараметров)
	ОбъектСервер = РеквизитФормыВЗначение("Объект");
	ТзнТаблицаИзвестныхStepDefinition = РеквизитФормыВЗначение("ТаблицаИзвестныхStepDefinition");
	
	Дерево = ОбъектСервер.ДеревоТестов;
	Дерево.Строки.Очистить();
	ТекДерево = Дерево;
	ТекУровень = 0;
	
	Для каждого Элем Из МассивРезультатОбходаКаталогов Цикл
		Если Элем.Уровень > ТекУровень Тогда
			ТекУровень = Элем.Уровень;
			НовСтр     = ТекДерево.Строки.Добавить();
			ТекДерево  = НовСтр;
		ИначеЕсли Элем.Уровень < ТекУровень Тогда
			Разн = ТекУровень - Элем.Уровень;
			Для Ккк = 1 По Разн Цикл
				НовСтр = НовСтр.Родитель;
			КонецЦикла;
			НовСтр     = НовСтр.Родитель.Строки.Добавить();
			ТекУровень = Элем.Уровень;
			ТекДерево  = НовСтр;
		Иначе	
			НовСтр     = ТекДерево.Родитель.Строки.Добавить();
			ТекДерево  = НовСтр;
		КонецЕсли;  
		
		Если Элем.Каталог Тогда
			//НовСтр            = ТекСтроки.Строки.Добавить();
			НовСтр.Каталог    = Истина;
			НовСтр.ПолныйПуть = Элем.ПолныйПуть;
			НовСтр.Имя        = Элем.Имя;
		ИначеЕсли Элем.Фича Тогда
			//НовСтр            = ТекСтроки.Строки.Добавить();
			НовСтр.Фича        = Истина;
			НовСтр.ТипКартинки = 1;
			НовСтр.ПолныйПуть  = Элем.ПолныйПуть;
			НовСтр.Имя         = Элем.Имя;
		КонецЕсли;  
		
	КонецЦикла;
	
	УдалитьПустыеКаталогиИзДерева(ОбъектСервер.ДеревоТестов);
	
	ВременноеИмяФайла = ПолучитьИмяВременногоФайла("epf");
	ДвДанныеvbFeatureReader.Записать(ВременноеИмяФайла);
	FeatureReader = ВнешниеОбработки.Создать(ВременноеИмяФайла,Ложь);
	
	
	Если Не СтруктураПараметров.Свойство("ТаблицаУжеСуществующихСценариев") Тогда
		ТаблицаУжеСуществующихСценариевСервер = ПреобразоватьМассивТаблицаУжеСуществующихСценариевВТаблицуЗначений(СтруктураПараметров.ТаблицаУжеСуществующихСценариевУФ);
		СтруктураПараметров.Вставить("ТаблицаУжеСуществующихСценариев",ТаблицаУжеСуществующихСценариевСервер);
	КонецЕсли;	 
	
	
	МассивКаталоговДляПроверкиНаПустоту = Новый Массив;
	СтруктураПараметров.Вставить("МассивКаталоговДляПроверкиНаПустоту",МассивКаталоговДляПроверкиНаПустоту);
	
	
	
	
	ЗаполнитьСтрокиДереваФичамиСервер(Дерево,FeatureReader,ТзнТаблицаИзвестныхStepDefinition,СтруктураПараметров);
	
	
	
	
	УдалитьПустыеКаталоги(МассивКаталоговДляПроверкиНаПустоту);
	СтруктураПараметров.МассивКаталоговДляПроверкиНаПустоту = Неопределено;
	СтруктураПараметров.ТаблицаУжеСуществующихСценариев = Неопределено;
	Если СтруктураПараметров.Свойство("КешФич") Тогда
		СтруктураПараметров.КешФич = Неопределено;
	КонецЕсли;	 
	
	
	УдалитьФайлы(ВременноеИмяФайла);
	
	ЗначениеВРеквизитФормы(ТзнТаблицаИзвестныхStepDefinition,"ТаблицаИзвестныхStepDefinition");
	ЗначениеВРеквизитФормы(ОбъектСервер,"Объект");
	
КонецПроцедуры

&НаКлиенте
Функция ПолучитьПутьКFeatureReader()
	ПутьКФайлу = ДополнитьСлешВПуть(Объект.КаталогИнструментов) + "vbFeatureReader.epf";
	
	Если Не ФайлСуществуетКомандаСистемы(ПутьКФайлу) Тогда
		ВызватьИсключение "Файл <vbFeatureReader.epf> не найден в каталоге инструментов <" + СокрЛП(Объект.КаталогИнструментов) + ">";
	КонецЕсли;	 
	
	Возврат ПутьКФайлу;
КонецФункции

&НаКлиенте
Процедура ЗаполнитьДерево(Каталог,ДополнительныеПараметры,СтруктураПараметров)
	Файл = Новый Файл(Каталог);
	МассивРезультатОбходаКаталогов = Новый Массив;
	
	СтруткураФайла = Новый Структура;
	СтруткураФайла.Вставить("Каталог",Истина);
	СтруткураФайла.Вставить("Имя",Файл.Имя);
	СтруткураФайла.Вставить("ПолныйПуть",Каталог);
	СтруткураФайла.Вставить("Уровень",1);
	
	МассивРезультатОбходаКаталогов.Добавить(СтруткураФайла);
	
	Уровень = 2;
	ТекРодитель = Неопределено;
	КолЭлементовДобавлено = 0;
	ОбходКаталогов(Каталог,МассивРезультатОбходаКаталогов,Уровень,ДополнительныеПараметры,ТекРодитель,КолЭлементовДобавлено);    
	
	ДвДанныеvbFeatureReader = Новый ДвоичныеДанные(ПолучитьПутьКFeatureReader());
	
	СтруктураПараметров.Вставить("МассивРезультатОбходаКаталогов",МассивРезультатОбходаКаталогов);
	ЗаполнитьДеревоЗначенийПоМассивуСервер(МассивРезультатОбходаКаталогов,ДвДанныеvbFeatureReader,СтруктураПараметров);
	
КонецПроцедуры


&НаКлиенте
Процедура ЗаполнитьДеревоФич(СтруктураПараметров)
	КаталогИнструментов     = СтруктураПараметров.КаталогИнструментов;
	КаталогФич              = СтруктураПараметров.КаталогФич;
	МассивСообщений         = СтруктураПараметров.МассивСообщений;
	DebugLog                = СтруктураПараметров.DebugLog;
	КаталогиБиблиотек       = СтруктураПараметров.КаталогиБиблиотек;
	ДополнительныеПараметры = СтруктураПараметров.ДополнительныеПараметры;
	
	СтруктураПараметров.ДополнительныеПараметры = Неопределено;//они не могут быть сериализованы в поздних версиях платформы
	
	ПутьКФичам = Новый Файл(КаталогФич);
	Если ЕстьПоддержкаАсинхронныхВызовов Тогда
		Если Не ПолучитьЗначениеПоРанееСобраннойИнформации(ДополнительныеПараметры,"КаталогФич","Существует") Тогда
			Возврат;
		КонецЕсли;	 
	Иначе	
		Если Не ПутьКФичам.Существует() Тогда
			МассивСообщений.Добавить("Не найден путь " + КаталогФич);
			Возврат;
		КонецЕсли;	 
	КонецЕсли;	 
	
	Если ЕстьПоддержкаАсинхронныхВызовов Тогда
		ТаблицаКонтекстовОбработок = Новый Массив;
		ТаблицаИзвестныхStepDefinition.Очистить();
		МассивИменКонтекстовОбработок.Очистить();
	КонецЕсли;	
	
	Путь = ПутьКФичам.ПолноеИмя;
	СтруктураПараметров.Вставить("ИдетЗагрузкаИзКаталога",Истина);
	Если ЕстьПоддержкаАсинхронныхВызовов Тогда
		Если Не ПолучитьЗначениеПоРанееСобраннойИнформации(ДополнительныеПараметры,"КаталогФич","ЭтоКаталог") Тогда //это файл
			Путь = ПутьКФичам.Путь;
			СтруктураПараметров.Вставить("ИдетЗагрузкаИзКаталога",Ложь);
		КонецЕсли;	 
	Иначе	
		Если ПутьКФичам.ЭтоФайл() Тогда
			Путь = ПутьКФичам.Путь;
			СтруктураПараметров.Вставить("ИдетЗагрузкаИзКаталога",Ложь);
		КонецЕсли;	 
	КонецЕсли;	 
	
	ПолучитьУжеСуществующиеСнипетыИзОбработок(Путь, ДополнительныеПараметры);
	Для каждого Элем Из КаталогиБиблиотек Цикл
		ПолучитьУжеСуществующиеСнипетыИзОбработок(Элем.Значение, ДополнительныеПараметры);
	КонецЦикла;
	
	Если ЕстьПоддержкаАсинхронныхВызовов Тогда
		ТаблицаУжеСуществующихСценариев = Новый Массив();
	КонецЕсли; 
	
	МассивОбработанныхФайлов    = Новый Массив;
	ПолучитьУжеСуществующиеСценарииИзФич(Путь,ДополнительныеПараметры,МассивОбработанныхФайлов);
	Для каждого Элем Из КаталогиБиблиотек Цикл
		ПолучитьУжеСуществующиеСценарииИзФич(Элем.Значение,ДополнительныеПараметры,МассивОбработанныхФайлов);
	КонецЦикла;
	СтруктураПараметров.Вставить("ТаблицаУжеСуществующихСценариевУФ",ТаблицаУжеСуществующихСценариев);
	
	ЗаполнитьДерево(ПутьКФичам.ПолноеИмя,ДополнительныеПараметры,СтруктураПараметров);
	
КонецПроцедуры

&НаКлиенте
Функция ПолучитьМассивДляПоискаДублейФайлов(МассивФайлов)
	Массив = Новый Массив;
	
	Для каждого Файл Из МассивФайлов Цикл
		Массив.Добавить(Файл.ПолноеИмя);
	КонецЦикла;
	
	Возврат Массив;
КонецФункции	

&НаКлиенте
Процедура ПолучитьУжеСуществующиеСценарииИзФич(Знач КаталогФич,ДополнительныеПараметры = Неопределено,МассивУжеОбработанныхаФайлов)
	Файл = Новый Файл(КаталогФич);
	
	НачальныйКаталог = КаталогФич;
	КаталогПоиска    = НачальныйКаталог;
	
	Файл = Новый Файл(НачальныйКаталог);
	Если НРег(Файл.Расширение) = ".feature" Тогда
		КаталогПоиска = Файл.Путь;
	КонецЕсли;	 
	
	Отладка("Ищу сценарии в каталоге " + КаталогПоиска);
	
	//Сообщить("КаталогПоиска="+КаталогПоиска);
	Если ЕстьПоддержкаАсинхронныхВызовов Тогда
		МассивФайлов = ПолучитьЗначениеПоРанееСобраннойИнформации(ДополнительныеПараметры,КаталогФич,"НайденныеФайлы"); //это файлы по данной библиотеке
		Если МассивФайлов = Неопределено Тогда
			МассивФайлов = ПолучитьЗначениеПоРанееСобраннойИнформации(ДополнительныеПараметры,"ПоискFeature","НайденныеФайлы");
		КонецЕсли;	 
		
		Ном = 0;
		Для каждого Библ Из Объект.КаталогиБиблиотек Цикл
			Ном = Ном + 1;
			
			МассивДляПоискаДублейФайлов = ПолучитьМассивДляПоискаДублейФайлов(МассивФайлов);
			
			МассивФайловБиблиотека = ПолучитьЗначениеПоРанееСобраннойИнформации(ДополнительныеПараметры,"БиблиотекаФич"+Ном,"НайденныеФайлы");
			Для каждого Элем Из МассивФайловБиблиотека Цикл
				Если МассивДляПоискаДублейФайлов.Найти(Элем.ПолноеИмя) <> Неопределено Тогда
					Продолжить;
				КонецЕсли;	 
				
				МассивФайлов.Добавить(Элем);
			КонецЦикла;
		КонецЦикла;
		
	Иначе	
		МассивФайлов = НайтиФайлы(КаталогПоиска,"*.feature",Истина);
	КонецЕсли;	 
	
	Для Каждого Файл Из МассивФайлов Цикл
		Если НРег(Файл.Расширение) <> ".feature" Тогда
			Продолжить;
		КонецЕсли;	 
		
		ИмяФайла = Файл.ПолноеИмя;
		Текст = Новый ЧтениеТекста;
		Текст.Открыть(ИмяФайла,"UTF-8");
		
		Если МассивУжеОбработанныхаФайлов.Найти(ИмяФайла) <> Неопределено Тогда
			Продолжить;
		КонецЕсли; 
		
		МассивУжеОбработанныхаФайлов.Добавить(ИмяФайла);
		
		
		
		
		Если НЕ ЕстьПоддержкаАсинхронныхВызовов Тогда
			ВерсияФайла = Файл.ПолучитьВремяИзменения();
			
			
			ИДВерсииФайла = МассивВерсийFeatureИмяФайла.Найти(ИмяФайла);
			Если ИДВерсииФайла = Неопределено Тогда
				МассивВерсийFeatureИмяФайла.Добавить(ИмяФайла);
				МассивВерсийFeatureВерсия.Добавить(ВерсияФайла);
			Иначе	
				Если МассивВерсийFeatureВерсия[ИДВерсииФайла] <> ВерсияФайла Тогда
					//значит файл изменился
					//обновляем версию и удаляем старые снипеты
					МассивВерсийFeatureВерсия[ИДВерсииФайла] = ВерсияФайла;
					
					
					МассивИД = Новый Массив;
					Ном = -1;
					Для каждого Элем Из ТаблицаУжеСуществующихСценариев Цикл
						Ном = Ном + 1;
						Если Элем.ИмяФайла = ИмяФайла Тогда
							МассивИД.Добавить(Ном);
						КонецЕсли; 
						
					КонецЦикла;
					
					Для Ккк = 0 По МассивИД.Количество()-1 Цикл
						ИД = МассивИД[МассивИД.Количество()-1 - Ккк];
						ТаблицаУжеСуществующихСценариев.Удалить(ИД);
					КонецЦикла;
					
					Отладка("Загрузил новую версию: " + Файл.ПолноеИмя);
				Иначе
					//значит уже актуальная версия файла загружена
					//Сообщить("!!!!!!!!!!!!!!!!!!! " + Файл.ПолноеИмя);
					Продолжить;
				КонецЕсли; 
			КонецЕсли; 
		КонецЕсли; 
		
		
		
		
		НашлиТегExportScenarios = Ложь;
		ДобавлятьШаги = Ложь;
		Пока Истина Цикл
			Стр = Текст.ПрочитатьСтроку();
			Если Стр = Неопределено Тогда
				Прервать;
			КонецЕсли;	 
			
			Стр = СокрЛП(Стр);
			СтрНРег = НРег(Стр);
			
			Если Стр = "" Тогда
				Продолжить;
			КонецЕсли;	 
			
			Если СтрНРег = "@exportscenarios" Тогда
				НашлиТегExportScenarios = Истина;
			КонецЕсли;	 
			
			
			Если Лев(СтрНРег,1) = "@" Тогда
				Продолжить;
			КонецЕсли;	 
			Если Лев(СтрНРег,1) = "#" Тогда
				Продолжить;
			КонецЕсли;	 
			
			Если НашлиТегExportScenarios Тогда
				Если Лев(СтрНРег,9) = "сценарий:" Тогда
					ДобавлятьШаги = Истина;
					ИмяСценария = СокрЛП(Сред(Стр,10));
					ТаблицаШагов = Новый Массив;
					ТаблицаУжеСуществующихСценариев.Добавить(ПолучитьСтруктуруДляСценария(ИмяСценария,ИмяФайла,ТаблицаШагов));
					Продолжить;
				ИначеЕсли Лев(СтрНРег,19) = "структура сценария:" Тогда
					ДобавлятьШаги = Ложь;
					Продолжить;
				КонецЕсли;	
				
				Если ДобавлятьШаги Тогда
					ТаблицаШагов.Добавить(Стр);
				КонецЕсли;	 
			КонецЕсли;	 
		КонецЦикла;	
		
		Текст.Закрыть();
		
	КонецЦикла;
	
	
	
КонецПроцедуры

&НаКлиенте
Функция ПолучитьСтруктуруДляСценария(ИмяСценария,ИмяФайла,ТаблицаШагов)
	Структура = Новый Структура;
	Структура.Вставить("ИмяСценария",ИмяСценария);
	Структура.Вставить("ИмяФайла",ИмяФайла);
	Структура.Вставить("ТаблицаШагов",ТаблицаШагов);
	Структура.Вставить("ДвоичныеДанные",Новый ДвоичныеДанные(ИмяФайла));
	
	Возврат Структура;
КонецФункции	

&НаКлиенте
Функция ПолучитьЗначениеПоРанееСобраннойИнформации(ДополнительныеПараметры, ИмяПараметра, ЗначениеПараметра)
	МассивДействий = ДополнительныеПараметры.МассивДействий;
	Для каждого Элем Из МассивДействий Цикл
		Если Элем.ИмяПараметра = ИмяПараметра Тогда
			Возврат Элем[ЗначениеПараметра];
		КонецЕсли;	 
	КонецЦикла;
КонецФункции	

&НаКлиенте
//Объединяем относительные пути файловой системы в один
// при передаче Путь = ../test/file.txt и ПутьОтносительно=c:\work\ возращаем c:\test\file.txt
// при передаче Путь = ./test/file.txt и ПутьОтносительно=c:\work\ возращаем c:\work\test\file.txt
// если в начале нет точки, считаем этот путь полным. 
Функция ПолучитьПолныйПутьОтносительноКаталогаОбработки(Знач Путь, Знач ПутьОтносительно)
	Перем Результат;
	Результат = Путь;
	Если Лев(СокрЛП(Путь), 1) = "." Тогда 
		ФайлОбработки = Новый Файл(ПутьОтносительно);
		КаталогОбработки = ДополнитьСлешВПуть(?(ФайлОбработки.ЭтоКаталог(), ФайлОбработки.ПолноеИмя, ФайлОбработки.Путь));
		ФайлПути = Новый Файл(КаталогОбработки+Путь);
		
		Результат = ФайлПути.ПолноеИмя;
	КонецЕсли;
	
	Возврат Результат;
	
КонецФункции

&НаКлиенте
Функция ПроверитьСуществованиеКаталогаИнструментов(ИмяФайла, ДополнительныеПараметры = Неопределено, ПутьКОбработке)
	Перем ПутьФайла;
	Если ЕстьПоддержкаАсинхронныхВызовов Тогда
		Возврат ПолучитьЗначениеПоРанееСобраннойИнформации(ДополнительныеПараметры,"КаталогИнструментов","Существует");
	Иначе	
		ПутьФайла = ПолучитьПолныйПутьОтносительноКаталогаОбработки(ИмяФайла, ПутьКОбработке);
		ФайлПроверкаСуществования = Новый Файл(ПутьФайла);
		Если НЕ ФайлПроверкаСуществования.Существует() Тогда
			Сообщить("Не найден каталог инструментов: " + ИмяФайла);
			Возврат Ложь;
		КонецЕсли;	   
		
	КонецЕсли;	 
	Возврат Истина;
КонецФункции	

&НаКлиенте
Функция ПроверитьСуществованиеКаталогаБиблиотек(ДополнительныеПараметры = Неопределено, ПутьКОбработке)
	Перем ПутьФайла;
	
	БылиОшибки = Ложь;
	Если ЕстьПоддержкаАсинхронныхВызовов Тогда
		Ном = 0;
		Для каждого Элем Из Объект.КаталогиБиблиотек Цикл
			Ном = Ном + 1;
			Если НЕ ПолучитьЗначениеПоРанееСобраннойИнформации(ДополнительныеПараметры, "КаталогиБиблиотек"+Ном, "Существует") Тогда
				БылиОшибки = Истина;
			КонецЕсли;	  
		КонецЦикла;	
	Иначе	
		Для каждого Элем Из Объект.КаталогиБиблиотек Цикл
			ПутьФайла = ПолучитьПолныйПутьОтносительноКаталогаОбработки(Элем.Значение, ПутьКОбработке);
			ФайлПроверкаСуществования = Новый Файл(ПутьФайла);
			Если НЕ ФайлПроверкаСуществования.Существует() Тогда
				Сообщить("Не найден каталог библиотеки: " + Элем.Значение);
				БылиОшибки = Истина;
			КонецЕсли;	   
		КонецЦикла;
		
	КонецЕсли;	 
	
	Возврат Не БылиОшибки;
	
КонецФункции


&НаСервере
Процедура ЗаполнитьИДСтрокиДереваСервер(МассивИменКонтекстовОбработок,ДопПараметры)
	
	ДеревоФорма = Объект.ДеревоТестов;
	ОбъектСервер = РеквизитФормыВЗначение("Объект");
	ТзнТаблицаИзвестныхStepDefinition = РеквизитФормыВЗначение("ТаблицаИзвестныхStepDefinition");
	МассивСтрокДереваДанныеФормы = Новый Массив;
	ЗаполнитьИДСтрокиВДереве(ОбъектСервер.ДеревоТестов,МассивСтрокДереваДанныеФормы,МассивИменКонтекстовОбработок,ТзнТаблицаИзвестныхStepDefinition,ДопПараметры);
	ЗначениеВРеквизитФормы(ОбъектСервер,"Объект");
	
КонецПроцедуры

&НаКлиенте
Процедура ДобавитьДействиеВМассивАсинхроныхСобытий(Массив,Путь,ИмяПараметра,ТипПараметра)
	
	СтруктураФайла = Новый Структура;
	СтруктураФайла.Вставить("ИмяФайла",Путь);
	СтруктураФайла.Вставить("ИмяПараметра",ИмяПараметра);
	СтруктураФайла.Вставить("ТипПараметра",ТипПараметра);
	
	Массив.Добавить(СтруктураФайла);
	
КонецПроцедуры

&НаКлиенте
Процедура ДобавитьСканированиеКаталогов(Массив)
	Перем ПутьФайла, ПутьКОбработке;

	//FIXME: необходимо вынести в реквизит формы.
	ПутьКОбработке = ПолучитьПутьКОбработкеСервер();
	ДобавитьДействиеВМассивАсинхроныхСобытий(Массив,"","ПоискEPF","СканированиеКаталогаПоискEPF");
	ДобавитьДействиеВМассивАсинхроныхСобытий(Массив,"","ПоискFeature","СканированиеКаталогаПоискFeature");
	Ном = 0;
	Для каждого Элем Из Объект.КаталогиБиблиотек Цикл
		Ном = Ном + 1;
		ПутьФайла = ПолучитьПолныйПутьОтносительноКаталогаОбработки(Элем.Значение, ПутьКОбработке);
		ДобавитьДействиеВМассивАсинхроныхСобытий(Массив,"",ПутьФайла,"СканированиеКаталогаПоискEPF");
		ДобавитьДействиеВМассивАсинхроныхСобытий(Массив,"","БиблиотекаФич" + Ном,"СканированиеКаталогаПоискFeature");
	КонецЦикла;
	
КонецПроцедуры

&НаКлиенте
Процедура ДобавитьМассивСостоянийФайлов(Массив)
	Перем ПутьФайла, ПутьКОбработке;
	
	ДобавитьДействиеВМассивАсинхроныхСобытий(Массив,Объект.КаталогИнструментов,"КаталогИнструментов","РаботаСФайлом");
	ДобавитьДействиеВМассивАсинхроныхСобытий(Массив, ДополнитьСлешВПуть(Объект.КаталогИнструментов) + "vbFeatureReader.epf","vbFeatureReader","РаботаСФайлом");
	ДобавитьДействиеВМассивАсинхроныхСобытий(Массив,Объект.КаталогOutputAllure,"КаталогOutputAllure","РаботаСФайлом");
	ДобавитьДействиеВМассивАсинхроныхСобытий(Массив,Объект.КаталогOutputxUnit,"КаталогOutputxUnit","РаботаСФайлом");
	ДобавитьДействиеВМассивАсинхроныхСобытий(Массив,Объект.КаталогOutputИнструкцияHTML,"КаталогOutputИнструкцияHTML","РаботаСФайлом");
	ДобавитьДействиеВМассивАсинхроныхСобытий(Массив,Объект.КаталогФич,"КаталогФич","РаботаСФайлом");
	
	//FIXME: необходимо вынести в реквизит формы.
	ПутьКОбработке = ПолучитьПутьКОбработкеСервер();

	Ном = 0;
	Для каждого Элем Из Объект.КаталогиБиблиотек Цикл
		Ном = Ном + 1;
		ПутьФайла = ПолучитьПолныйПутьОтносительноКаталогаОбработки(Элем.Значение, ПутьКОбработке);
		ДобавитьДействиеВМассивАсинхроныхСобытий(Массив,ПутьФайла,"КаталогиБиблиотек"+Ном,"РаботаСФайлом");
	КонецЦикла;
	
КонецПроцедуры	

&НаКлиенте
Процедура ПолучитьСинхроноСостоянияОбъектовФайловойСистемы(ДопПараметры);
	
КонецПроцедуры

&НаКлиенте
Процедура ОбработатьАсинхроноСледующийФайл(ДополнительныеПараметры)
	ДополнительныеПараметры.ТекИдМассива = ДополнительныеПараметры.ТекИдМассива + 1;
	ПолучитьАсинхроноСостоянияОбъектовФайловойСистемы(ДополнительныеПараметры);
КонецПроцедуры

&НаКлиенте
Процедура ОбработчикНачатьПроверкуЭтоКаталог(ЭтоКаталог,ДополнительныеПараметры) Экспорт
	
	ТекИдМассива   = ДополнительныеПараметры.ТекИдМассива;
	МассивДействий = ДополнительныеПараметры.МассивДействий;
	СтруктураФайла = МассивДействий[ТекИдМассива];
	СтруктураФайла.Вставить("ЭтоКаталог",ЭтоКаталог);
	
	Отладка("ОбработчикНачатьПроверкуЭтоКаталог. " + СтруктураФайла.ИмяПараметра + ": " + СтруктураФайла.ИмяФайла + ". ЭтоКаталог="+ЭтоКаталог);
	ОбработатьАсинхроноСледующийФайл(ДополнительныеПараметры);
	
КонецПроцедуры

&НаКлиенте
Процедура ОбработчикНачатьПроверкуСуществования(Существует,ДополнительныеПараметры) Экспорт
	ТекИдМассива   = ДополнительныеПараметры.ТекИдМассива;
	МассивДействий = ДополнительныеПараметры.МассивДействий;
	СтруктураФайла = МассивДействий[ТекИдМассива];
	СтруктураФайла.Вставить("Существует",Существует);
	
	Отладка("ОбработчикНачатьПроверкуСуществования. " + СтруктураФайла.ИмяПараметра + ": " + СтруктураФайла.ИмяФайла + ". Существует="+Существует);
	
	Если Существует Тогда
		Файл = Новый Файл(СтруктураФайла.ИмяФайла);
		ОписаниеОповещения = Вычислить("Новый ОписаниеОповещения(""ОбработчикНачатьПроверкуЭтоКаталог"",ЭтаФорма,ДополнительныеПараметры)");
		Выполнить("Файл.НачатьПроверкуЭтоКаталог(ОписаниеОповещения)");
	Иначе
		ОбработатьАсинхроноСледующийФайл(ДополнительныеПараметры);
	КонецЕсли;	 
	
КонецПроцедуры

&НаКлиенте
Процедура ОбработчикНачатьПоискФайлов(НайденныеФайлы,ДополнительныеПараметры) Экспорт
	ТекИдМассива   = ДополнительныеПараметры.ТекИдМассива;
	МассивДействий = ДополнительныеПараметры.МассивДействий;
	СтруктураФайла = МассивДействий[ТекИдМассива];
	СтруктураФайла.Вставить("НайденныеФайлы",НайденныеФайлы);
	
	ОбработатьАсинхроноСледующийФайл(ДополнительныеПараметры);
КонецПроцедуры

&НаКлиенте
Процедура ПолучитьАсинхроноСостоянияОбъектовФайловойСистемы(ДополнительныеПараметры);
	ТекИдМассива   = ДополнительныеПараметры.ТекИдМассива;
	МассивДействий = ДополнительныеПараметры.МассивДействий;
	Если ТекИдМассива > (МассивДействий.Количество()-1) Тогда
		Если ДополнительныеПараметры.НадоЗагрузитьФичи Тогда
			ЗагрузитьФичиПродолжение(ДополнительныеПараметры);
		КонецЕсли;	 
		Если ДополнительныеПараметры.НадоГенерироватьEPF Тогда
			СоздатьШаблоныОбработокПродолжение(ДополнительныеПараметры);
		КонецЕсли;	 
		Возврат;
	КонецЕсли;	 
	
	СтруктураФайла = МассивДействий[ТекИдМассива];
	Если СтруктураФайла.ТипПараметра = "РаботаСФайлом" Тогда
		Файл = Новый Файл(СтруктураФайла.ИмяФайла);
		ОписаниеОповещения = Вычислить("Новый ОписаниеОповещения(""ОбработчикНачатьПроверкуСуществования"",ЭтаФорма,ДополнительныеПараметры)");
		Выполнить("Файл.НачатьПроверкуСуществования(ОписаниеОповещения)");
	ИначеЕсли	Найти(СтруктураФайла.ТипПараметра,"СканированиеКаталогаПоиск") > 0 Тогда
		Если НЕ ПолучитьЗначениеПоРанееСобраннойИнформации(ДополнительныеПараметры,"КаталогФич","Существует") Тогда
			ОбработатьАсинхроноСледующийФайл(ДополнительныеПараметры);
			Возврат;
		КонецЕсли;	 
		
		Если (СтруктураФайла.ИмяПараметра = "ПоискEPF") или (СтруктураФайла.ИмяПараметра = "ПоискFeature") или (Лев(СтруктураФайла.ИмяПараметра,13) = "БиблиотекаФич") Тогда
			//значит мы ищем родные epf для фич
			ПутьКФичам = Новый Файл(Объект.КаталогФич);
			Путь = ПутьКФичам.ПолноеИмя;
			Если Не ПолучитьЗначениеПоРанееСобраннойИнформации(ДополнительныеПараметры,"КаталогФич","ЭтоКаталог") Тогда //это файл
				Путь = ПутьКФичам.Путь;
			КонецЕсли;	 
			
			
			Если Лев(СтруктураФайла.ИмяПараметра,13) = "БиблиотекаФич" Тогда
				Ном = СтрЗаменить(СтруктураФайла.ИмяПараметра,"БиблиотекаФич","");
				Ном = СтрЗаменить(Ном,Символы.НПП,"");
				Ном = Число(Ном);
				Путь = Объект.КаталогиБиблиотек[Ном-1].Значение;
			КонецЕсли;	 
			
		Иначе
			Путь = СтруктураФайла.ИмяПараметра;
		КонецЕсли;	 
		
		Маска = "*." + НРег(СтрЗаменить(СтруктураФайла.ТипПараметра,"СканированиеКаталогаПоиск",""));
		ОписаниеОповещения = Вычислить("Новый ОписаниеОповещения(""ОбработчикНачатьПоискФайлов"",Этаформа,ДополнительныеПараметры)");
		
		Если СтруктураФайла.ТипПараметра = "СканированиеКаталогаПоискFeature" Тогда
			Маска = "*";
		КонецЕсли;	 
		Выполнить("НачатьПоискФайлов(ОписаниеОповещения,Путь,Маска,Истина)"); 
	Иначе
		Сообщить("Неивестный ТипПараметра в ПолучитьАсинхроноСостоянияОбъектовФайловойСистемы: " + СтруктураФайла.ТипПараметра);
	КонецЕсли;	 
	
КонецПроцедуры

&НаКлиенте
Процедура ЗагрузитьФичиПродолжение(ДополнительныеПараметры = Неопределено)
	
	ЭтаФорма.ТекущийЭлемент = Элементы.ГруппаЗапускТестов;

	КаталогИнструментов = Объект.КаталогИнструментов;
	КаталогФич          = Объект.КаталогФич;
	DebugLog            = Объект.DebugLog;
	КаталогиБиблиотек   = Объект.КаталогиБиблиотек;
	ПутьКОбработке		= ПолучитьПутьКОбработкеСервер();
	
	Если НЕ ПроверитьСуществованиеКаталогаБиблиотек(ДополнительныеПараметры, ПутьКОбработке) Тогда
		Возврат;
	КонецЕсли;	 
	
	Если НЕ ПроверитьСуществованиеКаталогаИнструментов(КаталогИнструментов, ДополнительныеПараметры, ПутьКОбработке) Тогда
		СделатьСообщение("Не заполнен служебный параметр КаталогИнструментов!");
		Возврат;
	КонецЕсли;	 
	
	ПарсерФич = "";
	
	СтруктураПараметров = Новый Структура;
	СтруктураПараметров.Вставить("КаталогИнструментов",КаталогИнструментов);
	СтруктураПараметров.Вставить("КаталогФич",КаталогФич);
	СтруктураПараметров.Вставить("ПутьКОбработке", ПутьКОбработке);
	
	МассивСообщений = Новый Массив;
	СтруктураПараметров.Вставить("МассивСообщений",МассивСообщений);
	СтруктураПараметров.Вставить("DebugLog",DebugLog);
	СтруктураПараметров.Вставить("КаталогиБиблиотек",КаталогиБиблиотек);
	СтруктураПараметров.Вставить("ДополнительныеПараметры",ДополнительныеПараметры);
	
	СтруктураПараметров.Вставить("СписокТеговИсключение",Объект.СписокТеговИсключение);
	СтруктураПараметров.Вставить("СписокТеговОтбор",Объект.СписокТеговОтбор);
	
	
	Попытка
		ЗаполнитьДеревоФич(СтруктураПараметров);
	Исключение
		Сообщить("Ошибка при постсроении дерева.");
		Сообщить("" + ОписаниеОшибки());
		Возврат;
	КонецПопытки;
	
	Для каждого Элем Из МассивСообщений Цикл
		Сообщить(Элем);
	КонецЦикла;
	
	ДопПараметры = Новый Структура;
	ДопПараметры.Вставить("РежимВыполненияСценарияСВыбранногоШага",Объект.РежимВыполненияСценарияСВыбранногоШага);
	Если Объект.РежимВыполненияСценарияСВыбранногоШага Тогда
		ДопПараметры.Вставить("ИдСтрокиШагаСКоторогоВыполнятьСценарий",СтрокаШагаСКоторогоНадоВыполнятьСценарий.ИдСтроки);
	КонецЕсли;	 
	ЗаполнитьИДСтрокиДереваСервер(МассивИменКонтекстовОбработок,ДопПараметры);
	
	ПодключитьОбработчикОжидания("РазвернутьДерево", 0.5, Истина);
	//РазвернутьДерево();
	//Отладка("Кол строк фич " +  Объект.ДеревоТестов.ПолучитьЭлементы().Количество());
	
	Если Объект.ПодключитьВнешниеОбработкиДляОтладки Тогда
		ПодключитьВнешниеОбработкиДляОтладки();
	КонецЕсли; 
	
	СделатьСообщение("Фичи загружены.");
	Если Объект.НадоВыполнитьСценарииПослеЗагрузкиФич Тогда
		ВыполнитьСценарии();
	ИначеЕсли Объект.НадоВыполнитьСценарииПослеЗагрузкиФичОдинРаз Тогда
		Объект.НадоВыполнитьСценарииПослеЗагрузкиФичОдинРаз = Ложь;
		ВыполнитьСценарии();
	КонецЕсли;
		
КонецПроцедуры

&НаКлиенте
Процедура ЗагрузитьФичи() Экспорт
	
	МассивДействий = Новый Массив;
	ДобавитьМассивСостоянийФайлов(МассивДействий);
	ДобавитьСканированиеКаталогов(МассивДействий);
	
	
	ДопПараметры = Новый Структура;
	ДопПараметры.Вставить("ТекИдМассива",0);
	ДопПараметры.Вставить("МассивДействий",МассивДействий);
	ДопПараметры.Вставить("НадоЗагрузитьФичи",Истина);
	ДопПараметры.Вставить("НадоГенерироватьEPF",Ложь);
	Если ЕстьПоддержкаАсинхронныхВызовов Тогда
		ПолучитьАсинхроноСостоянияОбъектовФайловойСистемы(ДопПараметры);
	Иначе
		ПолучитьСинхроноСостоянияОбъектовФайловойСистемы(ДопПараметры);
		ЗагрузитьФичиПродолжение();
	КонецЕсли;	 
	
КонецПроцедуры

&НаСервере
Функция ПолучитьВерсиюОбработкиСервер(ТолькоЦифры = Ложь)
	Объект1 = РеквизитФормыВЗначение("Объект");
	Возврат Объект1.ПолучитьВерсиюОбработки(Ложь,ТолькоЦифры);
КонецФункции

&НаСервере
Процедура ЗадатьУсловноеОформление();
	//УО = УсловноеОформление.Элементы.Добавить();
	//УО.Оформление.УстановитьЗначениеПараметра("ЦветФона",WebЦвета.Красный);  
	//ЭУ = УО.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
	//ЭУ.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Объект.ДеревоТестов.Имя"); 
	//ЭУ.ВидСравнения  = ВидСравненияКомпоновкиДанных.НеРавно;
	//ЭУ.ПравоеЗначение  = "4";
	//ОП = УО.Поля.Элементы.Добавить();
	//ОП.Поле = Новый ПолеКомпоновкиДанных("Объект.ДеревоТестов.Имя"); 
КонецПроцедуры

&НаСервере
Процедура ЗаполнитьКаталогИнструментовЕслиОнПустой()
	КаталогИнструментов = Объект.КаталогИнструментов;
	
	
	Если СокрЛП(КаталогИнструментов) = "" Тогда
		
		ИспользуемоеИмяФайла = ПолучитьПутьКОбработкеСервер();
		Если (Лев(ИспользуемоеИмяФайла,6) <> "e1cib/") и (Лев(ИспользуемоеИмяФайла,6) <> "e1cib\") Тогда
			Файл = Новый Файл(ИспользуемоеИмяФайла);
			КаталогИнструментов = Файл.Путь;
			Если Прав(КаталогИнструментов,1) =  "\" Тогда
				КаталогИнструментов = Лев(КаталогИнструментов,СтрДлина(КаталогИнструментов)-1);
			ИначеЕсли Прав(КаталогИнструментов,1) =  "/" Тогда
				КаталогИнструментов = Лев(КаталогИнструментов,СтрДлина(КаталогИнструментов)-1);
			КонецЕсли;	 
		Иначе	
			//попытаемся восстановить из настроек. Это нужно, когда Vanessa-Behavior вызвали программно, а затем сразу открыли интерактивно. В этом случае 1С подгружает версию из кеша от первой загрузки на сервере, и Объект().ИспользуемоеИмяФайла возвращает адрес в хранилище, а не имя исходного файла.
			Настройки = ХранилищеОбщихНастроек.Загрузить("VanessaBehaviorUF");
			
			Если ТипЗнч(Настройки) = Тип("Структура") Тогда
				Настройки.Свойство("КаталогИнструментов", КаталогИнструментов);
			КонецЕсли;	
		
		КонецЕсли;	
		
	КонецЕсли;	 
	
	Объект.КаталогИнструментов = КаталогИнструментов;
КонецПроцедуры

&НаСервере 
Процедура ЗаполнитьКонтекстноеМеню()
	Пункт1=Элементы.Добавить("ДеревоТестовКонтекстноеМенюПунктВыполнитьСценарий", Тип("КнопкаФормы"), Элементы.ДеревоТестов.КонтекстноеМеню);
	Пункт1.Заголовок=НСтр("ru='Выполнить выделенный сценарий';en='Invoke only selected scenarion'");
	Пункт1.ИмяКоманды="ВыполнитьВыделенныйСценарий";
	
	Пункт2=Элементы.Добавить("ДеревоТестовКонтекстноеМенюПунктОткрытьФичаФайл", Тип("КнопкаФормы"), Элементы.ДеревоТестов.КонтекстноеМеню);
	Пункт2.Заголовок=НСтр("ru='Открыть feature файл в редакторе';en='Open feature file in editor'");
	Пункт2.ИмяКоманды="ОткрытьФичаФайл";
	
	Пункт3=Элементы.Добавить("ДеревоТестовКонтекстноеМенюВыполнятьСценарийСЭтогоШага", Тип("КнопкаФормы"), Элементы.ДеревоТестов.КонтекстноеМеню);
	Пункт3.Заголовок=НСтр("ru='Выполнять сценарий с этого шага;en='Run scenario from that step'");
	Пункт3.ИмяКоманды="УстановитьПометкуВыполнятьСценарийСЭтогоШага";
	
	Пункт4=Элементы.Добавить("ДеревоТестовКонтекстноеМенюВыполнятьСценарииСначала", Тип("КнопкаФормы"), Элементы.ДеревоТестов.КонтекстноеМеню);
	Пункт4.Заголовок=НСтр("ru='Выполнять сценарии с начала';en='Run scenario from first step'");
	Пункт4.ИмяКоманды="СнятьПометкуВыполнятьСценарийСЭтогоШага";
	
	Пункт5=Элементы.Добавить("ДеревоТестовКонтекстноеМенюСвернутьДоФич", Тип("КнопкаФормы"), Элементы.ДеревоТестов.КонтекстноеМеню);
	Пункт5.Заголовок=НСтр("ru='Свернуть до фич';en='Switch to features'");
	Пункт5.ИмяКоманды="СвернутьДеревоДоФич";
	
	Пункт6=Элементы.Добавить("ДеревоТестовКонтекстноеМенюСвернутьДоСценариев", Тип("КнопкаФормы"), Элементы.ДеревоТестов.КонтекстноеМеню);
	Пункт6.Заголовок=НСтр("ru='Свернуть до сценариев';en='Switch to scenarios'");
	Пункт6.ИмяКоманды="СвернутьДеревоДоСценариев";
	
	Элементы.ДеревоТестовКонтекстноеМенюВыполнятьСценарииСначала.Видимость = Ложь;
КонецПроцедуры

&НаКлиенте
Функция ПолучитьСтруктуруПараметров(Стр)
	Результат = Новый Структура;
	
	Массив = РазложитьСтрокуВМассивПодстрок(Стр,";");
	Для каждого Элем Из Массив Цикл
		Поз = Найти(Элем,"=");
		Если Поз > 0 Тогда
			Ключ     = Лев(Элем,Поз-1);
			Значение = Сред(Элем,Поз+1);
			Попытка
				Результат.Вставить(Ключ,Значение);
			Исключение
				Сообщить("Не смог получить значение из строки запуска: " + Ключ);
			КонецПопытки;
		Иначе
			Если НЕ ПустаяСтрока(Элем) Тогда 
				Попытка
					Результат.Вставить(Элем,Истина);
				Исключение
					Сообщить("Не смог получить значение из строки запуска: " + Элем);
				КонецПопытки;
			КонецЕсли;
		КонецЕсли;	 
	КонецЦикла;
	
	Возврат Результат;
КонецФункции	

&НаКлиенте
Функция ПолучитьЗначениеПереданногоПараметра(СтруктураПараметров, ИмяПараметра)
	Если СтруктураПараметров.Свойство(ИмяПараметра) Тогда
		Возврат СтруктураПараметров[ИмяПараметра];
	Иначе	
		Возврат Неопределено;
	КонецЕсли;	 
КонецФункции	

&НаКлиенте 
Функция ПрочитатьСтруктуруИзJSONФайлаКлиент(VBParams)
	
	ПараметрыУФ            = Новый Структура;
	VBParamsДвоичныеДанные = Новый ДвоичныеДанные(VBParams);
	ПараметрыУФ.Вставить("VBParamsДвоичныеДанные",VBParamsДвоичныеДанные);
	
	Рез = ПрочитатьСтруктуруИзJSONФайлаСервер(VBParams,ПараметрыУФ);
	
	Возврат Рез;
	
КонецФункции

&НаСервере 
Функция ПрочитатьСтруктуруИзJSONФайлаСервер(VBParams,ПараметрыУФ)
	ОбъектСервер = РеквизитФормыВЗначение("Объект");
		
	Рез = ОбъектСервер.ПрочитатьСтруктуруИзJSONФайла(VBParams,ПараметрыУФ);
	
	Возврат Рез;
	
КонецФункции	

&НаКлиенте
Процедура ОчиститьСодержимоеКаталога(Знач ИмяКаталога)
	Если НЕ ФайлСуществуетКомандаСистемы(ИмяКаталога) Тогда
		Возврат;
	КонецЕсли;	 
	
	Если Найти(Прав(ИмяКаталога,1), "\/") > 0 Тогда
		ИмяКаталога = Лев(ИмяКаталога,СтрДлина(ИмяКаталога)-1);
	КонецЕсли;	 
	
	Если ЕстьПоддержкаАсинхронныхВызовов Тогда
		УдалитьКаталогКомандаСистемы(ИмяКаталога);
		СоздатьКаталогКомандаСистемы(ИмяКаталога);
	Иначе	
		МассивФайлов = НайтиФайлы(ИмяКаталога,"*.*",Ложь);
		Для каждого Файл Из МассивФайлов Цикл
			//Если Файл.Существует() Тогда
			Попытка
				УдалитьФайлыКомандаСистемы(Файл.ПолноеИмя);
			Исключение
				СделатьСообщение("Не смог удалить файл!!! " + Файл.ПолноеИмя);
			КонецПопытки;
			//КонецЕсли;	 
		КонецЦикла;
	КонецЕсли;	 
	
КонецПроцедуры

&НаКлиенте
Функция СоздатьСтруктуруПараметровЗапуска()
	Рез = Новый Структура;
	Рез.Вставить("StartFeaturePlayer", Ложь);
	Рез.Вставить("КаталогФич", "");
	Рез.Вставить("КаталогиБиблиотек", Новый Массив);
	Рез.Вставить("СписокТеговИсключение", Новый Массив);
	Рез.Вставить("СписокТеговОтбор", Новый Массив);
	Рез.Вставить("ДелатьСообщенияТранслитом", Ложь);
	Рез.Вставить("СоздаватьИнструкциюHTML", Ложь);
	Рез.Вставить("СоздаватьИнструкциюMarkdown", Ложь);
	Рез.Вставить("СоздаватьИнструкциюВидео", Ложь);
	Рез.Вставить("ДелатьЛогВыполненияСценариевВЖР", Ложь);
	Рез.Вставить("ЗакрытьTestClientПослеЗапускаСценариев", Ложь);
	Рез.Вставить("КаталогOutputИнструкцияHTML", "");
	Рез.Вставить("КаталогOutputИнструкцияMarkdown", "");
	Рез.Вставить("КаталогOutputИнструкцияВидео", "");
	Рез.Вставить("КаталогСкриптовСборкиВидео", "");
	Рез.Вставить("ДелатьОтчетВоВнутреннемФормате", Истина);
	Рез.Вставить("ДелатьОтчетВФорматеАллюр", Истина);
	Рез.Вставить("КаталогOutputAllure", "");
	Рез.Вставить("КаталогOutputAllureБазовый", "");
	Рез.Вставить("ДелатьОтчетВФорматеxUnit", Ложь);
	Рез.Вставить("КаталогOutputxUnit", "");
	Рез.Вставить("КаталогOutputxUnitБазовый", "");
	Рез.Вставить("ДобавлятьКИмениСценарияУловияВыгрузки", Ложь);
	Рез.Вставить("СоздаватьПодкаталогВКаталогеAllureДляЭтойСборки", Ложь);
	Рез.Вставить("ВыгружатьСтатусВыполненияСценариевВФайл", Ложь);
	Рез.Вставить("ПутьКФайлуДляВыгрузкиСтатусаВыполненияСценариев", "");
	Рез.Вставить("ВыполнитьСценарии", Ложь);
	Рез.Вставить("ЗавершитьРаботуСистемы", Ложь);
	Рез.Вставить("ИмяСборки", "");
	Рез.Вставить("ДелатьСкриншотПриВозникновенииОшибки", Ложь);
	Рез.Вставить("КомандаСделатьСкриншот", "");
	Рез.Вставить("КаталогOutputСкриншоты", "");
	Возврат Рез;
КонецФункции

&НаКлиенте
Функция СоздатьКоллекциюКомандЗапуска()
	Рез = СоздатьСтруктуруПараметровЗапуска();
	Рез.Вставить("StartFeaturePlayer", Новый Структура("Р,А", "StartFeaturePlayer","startfeatureplayer"));
	Рез.Вставить("КаталогФич", Новый Структура("Р,А", "КаталогФич","featurepath"));
	Рез.Вставить("КаталогиБиблиотек", Новый Структура("Р,А", "КаталогиБиблиотек","librarycatalogs"));
	Рез.Вставить("СписокТеговИсключение", Новый Структура("Р,А", "СписокТеговИсключение","ignoretags"));
	Рез.Вставить("СписокТеговОтбор", Новый Структура("Р,А", "СписокТеговОтбор","filtertags"));
	Рез.Вставить("ДелатьСообщенияТранслитом", Новый Структура("Р,А", "ДелатьСообщенияТранслитом","translatemassage"));
	Рез.Вставить("СоздаватьИнструкциюHTML", Новый Структура("Р,А", "СоздаватьИнструкциюHTML","htmlcreate"));
	Рез.Вставить("СоздаватьИнструкциюMarkdown", Новый Структура("Р,А", "СоздаватьИнструкциюMarkdown","markdowncreate"));
	Рез.Вставить("СоздаватьИнструкциюВидео", Новый Структура("Р,А", "СоздаватьИнструкциюВидео","videcreate"));
	Рез.Вставить("ДелатьЛогВыполненияСценариевВЖР", Новый Структура("Р,А", "ДелатьЛогВыполненияСценариевВЖР","logtogr"));
	Рез.Вставить("ЗакрытьTestClientПослеЗапускаСценариев", Новый Структура("Р,А", "ЗакрытьTestClientПослеЗапускаСценариев","closetestclient"));
	Рез.Вставить("КаталогOutputИнструкцияHTML", Новый Структура("Р,А", "КаталогOutputИнструкцияHTML","htmlpath"));
	Рез.Вставить("КаталогOutputИнструкцияMarkdown", Новый Структура("Р,А", "КаталогOutputИнструкцияMarkdown","markdownpath"));
	Рез.Вставить("КаталогOutputИнструкцияВидео", Новый Структура("Р,А", "КаталогOutputИнструкцияВидео","videopath"));
	Рез.Вставить("КаталогСкриптовСборкиВидео", Новый Структура("Р,А", "КаталогСкриптовСборкиВидео","videoscriptpath"));
	
	Рез.Вставить("ДелатьОтчетВоВнутреннемФормате", Новый Структура("Р,А", "ДелатьОтчетВоВнутреннемФормате","simplereport"));	 
	
	Рез.Вставить("ДелатьОтчетВФорматеАллюр", Новый Структура("Р,А", "ДелатьОтчетВФорматеАллюр","allurecreatereport"));	 
	Рез.Вставить("КаталогOutputAllure", Новый Структура("Р,А", "КаталогOutputAllure","allurepath"));	
	Рез.Вставить("КаталогOutputAllureБазовый", Новый Структура("Р,А", "КаталогOutputAllureБазовый","allurepathbase"));
	
	Рез.Вставить("ДелатьОтчетВФорматеxUnit", Новый Структура("Р,А", "ДелатьОтчетВФорматеxUnit","xunitcreatereport"));	 
	Рез.Вставить("КаталогOutputxUnit", Новый Структура("Р,А", "КаталогOutputxUnit","xunitpath"));	
	Рез.Вставить("КаталогOutputxUnitБазовый", Новый Структура("Р,А", "КаталогOutputxUnitБазовый","xunitpathbase"));
	
	Рез.Вставить("ДобавлятьКИмениСценарияУловияВыгрузки", Новый Структура("Р,А", "ДобавлятьКИмениСценарияУловияВыгрузки","addtofeaturefilter"));
	Рез.Вставить("СоздаватьПодкаталогВКаталогеAllureДляЭтойСборки", Новый Структура("Р,А", "СоздаватьПодкаталогВКаталогеAllureДляЭтойСборки","createsubfolderforbuild"));
	Рез.Вставить("ВыгружатьСтатусВыполненияСценариевВФайл", Новый Структура("Р,А", "ВыгружатьСтатусВыполненияСценариевВФайл","createlogs"));
	Рез.Вставить("ПутьКФайлуДляВыгрузкиСтатусаВыполненияСценариев", Новый Структура("Р,А", "ПутьКФайлуДляВыгрузкиСтатусаВыполненияСценариев","logpath"));
	Рез.Вставить("ВыполнитьСценарии", Новый Структура("Р,А", "ВыполнитьСценарии","vanessarun"));
	Рез.Вставить("ЗавершитьРаботуСистемы", Новый Структура("Р,А", "ЗавершитьРаботуСистемы","vanessashutdown"));
	Рез.Вставить("ИмяСборки", Новый Структура("Р,А", "ИмяСборки","buildname"));
	
	Рез.Вставить("ДелатьСкриншотПриВозникновенииОшибки", Новый Структура("Р,А", "ДелатьСкриншотПриВозникновенииОшибки","onerrorscreenshot"));
	Рез.Вставить("КомандаСделатьСкриншот", Новый Структура("Р,А", "КомандаСделатьСкриншот","commandscreenshot"));
	Рез.Вставить("КаталогOutputСкриншоты", Новый Структура("Р,А", "КаталогOutputСкриншоты","outputscreenshot"));
	
	Возврат Рез;
КонецФункции

&НаКлиенте
Функция НайтиКоманду(КоллекцияКоманды, КомандаЗапускаНРег)
	Для каждого КлючЗначение Из КоллекцияКоманды Цикл
		Если НРег(КлючЗначение.Значение) = НРег(КомандаЗапускаНРег) Тогда
			Возврат Истина;
		КонецЕсли;
	КонецЦикла;
	Возврат Ложь;
КонецФункции

&НаКлиенте
Функция ПрочитатьПеременныеСреды() 
	СоответствееПеременныхПути = Новый Соответствие;
	ИмяВременногоФайла = ПолучитьИмяВременногоФайла();
	
	Если ЭтоLinux Тогда 
		КомандаСистемы("sh -c 'env > "+ИмяВременногоФайла + "'");
	Иначе 
		КомандаСистемыРаботаСФайлами("set > """ + ИмяВременногоФайла + """");
	КонецЕсли;
	
	Попытка 
		Чтение = Новый ЧтениеТекста(ИмяВременногоФайла);
		Стр = Чтение.ПрочитатьСтроку();
		Пока Стр <> Неопределено Цикл 
			//Найдем ключ и значение
			Индекс = Найти(Стр, "=");
			Если Индекс > 0 Тогда 
				Ключ = Нрег(Лев(Стр, Индекс-1));
				Если ВРег(Лев(Ключ, 8))="VANESSA_" Тогда 
					Ключ = Сред(Ключ, 9);
					Значение = Сред(Стр, Индекс + 1);
					СоответствееПеременныхПути.Вставить(Ключ, Значение);
				КонецЕсли;
			КонецЕсли;
			Стр = Чтение.ПрочитатьСтроку();
		КонецЦикла;
	Исключение 
	КонецПопытки;
	
	КоллекцияКоммандЗапуска = СоздатьКоллекциюКомандЗапуска();
	СтруктураПараметров = Новый Структура;
	Для каждого ЭлементСтруктуры из КоллекцияКоммандЗапуска Цикл 
		Для каждого ЭлементПеременных из СоответствееПеременныхПути Цикл 
			Если НайтиКоманду(ЭлементСтруктуры.Значение, ЭлементПеременных.Ключ) Тогда 
				СтруктураПараметров.Вставить(ЭлементСтруктуры.Ключ, ЭлементПеременных.Значение);
				Прервать;
			КонецЕсли;
		КонецЦикла;		
	КонецЦикла;
	
	Возврат СтруктураПараметров;
	
КонецФункции

&НаКлиенте
Функция ОбъединитьПараметрыСУчетомПриоритета(ПараметрыЭталон, ПараметрыПриоритет, Параметры)
	СтруктутраПараметров = Новый Структура;
	Для каждого ключЗначение из ПараметрыЭталон Цикл 
		Значение = Неопределено;
		Если ТипЗнч(ПараметрыПриоритет) = Тип("Соответствие") Тогда 
			Если ПараметрыПриоритет.Получить(ключЗначение.Ключ) <> Неопределено Тогда
				Значение = ПараметрыПриоритет.Получить(ключЗначение.Ключ);
			КонецЕсли;
		ИначеЕсли ТипЗнч(ПараметрыПриоритет) = Тип("Структура") Тогда 
			ПараметрыПриоритет.Свойство(ключЗначение.Ключ, Значение);
		КонецЕсли;
		
		Если Значение = Неопределено Тогда 
			Если ТипЗнч(Параметры) = Тип("Соответствие") Тогда 
				Если Параметры.Получить(ключЗначение.Ключ) <> Неопределено Тогда
					Значение = Параметры.Получить(ключЗначение.Ключ);
				КонецЕсли;
			ИначеЕсли ТипЗнч(Параметры) = Тип("Структура") Тогда 
				Параметры.Свойство(ключЗначение.Ключ, Значение);
			КонецЕсли;			
		КонецЕсли;    
		
		ключЗначениеЗначение = Неопределено;
		Если Значение <> Неопределено Тогда 
			Если ТипЗнч(ключЗначение.Значение) = Тип("Булево") Тогда 
				Если НРег(Значение) = "истина" Тогда 
					ключЗначениеЗначение = Истина;
				ИначеЕсли Значение = "1" Тогда 
					ключЗначениеЗначение = Истина;
				ИначеЕсли Значение = "0" Тогда
					ключЗначениеЗначение = Ложь;
				КонецЕсли;
			ИначеЕсли ТипЗнч(ключЗначение.Значение) = Тип("Строка") Тогда  
				ключЗначениеЗначение = Строка(Значение);
			ИначеЕсли ТипЗнч(ключЗначение.Значение) = Тип("Массив") Тогда
				МассивПараметров = Новый Массив;
				Если ТипЗнч(Значение) = Тип("Строка") Тогда 
					МассивПараметров = РазложитьСтрокуВМассивПодстрок(Значение, ",");
				ИначеЕсли ТипЗнч(Значение) = Тип("Массив") Тогда
					МассивПараметров = Значение;
				КонецЕсли;
				ключЗначениеЗначение = МассивПараметров;
			КонецЕсли;
		КонецЕсли;
		СтруктутраПараметров.Вставить(ключЗначение.Ключ, ?(ключЗначениеЗначение = Неопределено, ключЗначение.Значение, ключЗначениеЗначение));
	КонецЦикла;
				                
	Возврат СтруктутраПараметров;
	
КонецФункции

&НаКлиенте
Функция ПреобразоватьПутьСТочкамиКНормальномуПути(ОригСтр)
	Если ЭтоLinux Тогда
		Возврат ОригСтр;
	КонецЕсли;	 
	
	Если Лев(ОригСтр,1) <> "." Тогда
		Возврат ОригСтр;
	КонецЕсли;	 
	
	
	ИмяВременногоФайлаКоманда = ПолучитьИмяВременногоФайла("cmd");
	ИмяВременногоФайлаЛог     = ПолучитьИмяВременногоФайла("txt");
	
	//ИмяВременногоФайлаКоманда = "h:\commons\temp\111.cmd";
	//ИмяВременногоФайлаЛог     = "h:\commons\temp\111.txt";
	
	
	Команда = "@echo on
				|for %%f in ( """ + ОригСтр + """ ) do set fullname=%%~ff
				|echo %fullname% > " + ИмяВременногоФайлаЛог;
				
	
	//Сообщить(""+ Команда);
	
	ЗТ = Новый ЗаписьТекста(ИмяВременногоФайлаКоманда,"UTF-8",,Ложь); 
	ЗТ.ЗаписатьСтроку(Команда); 
	
	ЗТ.Закрыть();
	
	
	
	
	retCode = -1;
	//ЗапуститьПриложение(ИмяВременногоФайлаКоманда,,Истина,retCode);
	КомандаСистемы(ИмяВременногоФайлаКоманда);
	
	
	Рез = ОригСтр;
	
	Текст = Новый ЧтениеТекста;
	Текст.Открыть(ИмяВременногоФайлаЛог,"UTF-8");
	
	Пока Истина Цикл
		Стр = Текст.ПрочитатьСтроку();
		Если Стр = Неопределено Тогда
			Прервать;
		КонецЕсли;	 
		
		Если СокрЛП(Стр) = "" Тогда
			Продолжить;
		КонецЕсли;	 
		
		
		Рез = СокрЛП(Стр);
		
	КонецЦикла;	
	
	Текст.Закрыть();
	
	Возврат Рез;
	
КонецФункции	

&НаКлиенте
Процедура ПреобразоватьПараметрыКоторыеНачинаютсяСТочкиКНормальнымПутям(СтруктураПараметров)
	МассивКлючей = Новый Массив;
	
	Для каждого ПараметрСборки Из СтруктураПараметров Цикл
		Если Лев(ПараметрСборки.Значение,1) = "." Тогда
			МассивКлючей.Добавить(ПараметрСборки.Ключ);
		КонецЕсли;	 
	КонецЦикла;
	
	Для каждого Ключ Из МассивКлючей Цикл
		Было  = СтруктураПараметров[Ключ];
		Стало = ПреобразоватьПутьСТочкамиКНормальномуПути(СтруктураПараметров[Ключ]);
		
		СтруктураПараметров.Вставить(Ключ,Стало);
	КонецЦикла;
КонецПроцедуры

&НаКлиенте
Процедура ЗапускВРежимеКоманднойСтроки()
	
	Если Объект.РежимСамотестирования Тогда
		Возврат;
	КонецЕсли;	 
	
	СтрЗапуска = СокрЛП(ПараметрЗапуска);
	//СтрЗапуска = "StartFeaturePlayer;VBParams=H:\Commons\vanessa-behavoir\tools\JSON\VBParams837UF.json";
	Если СтрЗапуска = "" Тогда
		Возврат;
	КонецЕсли;	
	
	СтруктураПараметров = ПолучитьСтруктуруПараметров(СтрЗапуска);
	ПреобразоватьПараметрыКоторыеНачинаютсяСТочкиКНормальнымПутям(СтруктураПараметров);
	
	ПараметрыЭталон = СоздатьСтруктуруПараметровЗапуска();
	ПеременныеСреды = ПрочитатьПеременныеСреды();
	StartFeaturePlayer = ПолучитьЗначениеПереданногоПараметра(СтруктураПараметров,"StartFeaturePlayer") = Истина Или ПолучитьЗначениеПереданногоПараметра(ПеременныеСреды, "StartFeaturePlayer") = Истина;
	Если StartFeaturePlayer = Истина Тогда
		Объект.ЗапускИзКоманднойСтроки = Истина;
		
		VBParams = ПолучитьЗначениеПереданногоПараметра(СтруктураПараметров,"VBParams");
		Если VBParams = Неопределено Тогда
			СделатьСообщение("Не найден путь к файлу JSON. Параметр: VBParams.");
			ПараметрыФайла = СоздатьСтруктуруПараметровЗапуска();
		Иначе 
			ПараметрыФайла = ПрочитатьСтруктуруИзJSONФайлаКлиент(VBParams);
			Если ПараметрыФайла = Неопределено Тогда
				СделатьСообщение("Ошибка чтения структуры JSON пропускаем чтение");
			КонецЕсли; 
		КонецЕсли;	 
		
		СтрутктураJSON = ОбъединитьПараметрыСУчетомПриоритета(ПараметрыЭталон, ПеременныеСреды, ПараметрыФайла);
		
		Если СтрутктураJSON = Неопределено Тогда
			СделатьСообщение("Ошибка чтения структуры JSON.");
			Возврат;
		КонецЕсли;
		
		ПреобразоватьПараметрыКоторыеНачинаютсяСТочкиКНормальнымПутям(СтрутктураJSON);
		
		ПромСтр = ПреобразоватьПутьСТочкамиКНормальномуПути(ПолучитьЗначениеПереданногоПараметра(СтрутктураJSON,"КаталогФич"));
		Если ПромСтр = Неопределено Тогда
			СделатьСообщение("В параметрах JSON не найден каталог Фич!");
			Возврат;
		КонецЕсли;	 
		
		Объект.КаталогФич = ПромСтр;
		
		Объект.КаталогиБиблиотек.Очистить();
		ЗначКаталогиБиблиотек = ПолучитьЗначениеПереданногоПараметра(СтрутктураJSON,"КаталогиБиблиотек");
		Если ТипЗнч(ЗначКаталогиБиблиотек) = Тип("Массив") Тогда
			Для Сч = 0 По ЗначКаталогиБиблиотек.Количество()-1 Цикл
				ЗначКаталогиБиблиотек[Сч] = ПреобразоватьПутьСТочкамиКНормальномуПути(ЗначКаталогиБиблиотек[Сч]);
			КонецЦикла;
				
			
			Объект.КаталогиБиблиотек.ЗагрузитьЗначения(ЗначКаталогиБиблиотек);
		КонецЕсли;  
		
		
		Объект.СписокТеговИсключение.Очистить();
		ЗначСписокТеговИсключение = ПолучитьЗначениеПереданногоПараметра(СтрутктураJSON,"СписокТеговИсключение");
		Если ТипЗнч(ЗначСписокТеговИсключение) = Тип("Массив") Тогда
			Объект.СписокТеговИсключение.ЗагрузитьЗначения(ЗначСписокТеговИсключение);
		КонецЕсли;  
		
		Объект.СписокТеговОтбор.Очистить();
		ЗначСписокТеговОтбор = ПолучитьЗначениеПереданногоПараметра(СтрутктураJSON,"СписокТеговОтбор");
		Если ТипЗнч(ЗначСписокТеговОтбор) = Тип("Массив") Тогда
			Объект.СписокТеговОтбор.ЗагрузитьЗначения(ЗначСписокТеговОтбор);
		КонецЕсли;  
		
		ЗнДелатьСообщенияТранслитом = ПолучитьЗначениеПереданногоПараметра(СтрутктураJSON,"ДелатьСообщенияТранслитом");
		Если ЗнДелатьСообщенияТранслитом = Истина Тогда
			Объект.ДелатьСообщенияТранслитом = Истина;
		КонецЕсли;	 
		
		ЗнСоздаватьИнструкциюHTML = ПолучитьЗначениеПереданногоПараметра(СтрутктураJSON,"СоздаватьИнструкциюHTML");
		Если ЗнСоздаватьИнструкциюHTML = Истина Тогда
			Объект.СоздаватьИнструкциюHTML = Истина;
		КонецЕсли;	 
		
		ЗнСоздаватьИнструкциюMarkdown = ПолучитьЗначениеПереданногоПараметра(СтрутктураJSON,"СоздаватьИнструкциюMarkdown");
		Если ЗнСоздаватьИнструкциюMarkdown = Истина Тогда
			Объект.СоздаватьИнструкциюMarkdown = Истина;
		КонецЕсли;	 
		
		ЗнСоздаватьИнструкциюВидео = ПолучитьЗначениеПереданногоПараметра(СтрутктураJSON,"СоздаватьИнструкциюВидео");
		Если ЗнСоздаватьИнструкциюВидео = Истина Тогда
			Объект.СоздаватьИнструкциюВидео = Истина;
		КонецЕсли;	 
		
		ЗнДелатьЛогВыполненияСценариевВЖР = ПолучитьЗначениеПереданногоПараметра(СтрутктураJSON,"ДелатьЛогВыполненияСценариевВЖР");
		Если ЗнДелатьЛогВыполненияСценариевВЖР = Истина Тогда
			Объект.ДелатьЛогВыполненияСценариевВЖР = Истина;
		КонецЕсли;	 
		
		
		
		//по скриншотам - начало
		ЗнДелатьСкриншотПриВозникновенииОшибки = ПолучитьЗначениеПереданногоПараметра(СтрутктураJSON,"ДелатьСкриншотПриВозникновенииОшибки");
		Если ЗнДелатьСкриншотПриВозникновенииОшибки = Истина Тогда
			Объект.ДелатьСкриншотПриВозникновенииОшибки = Истина;
		КонецЕсли;	 
		
		ЗнКомандаСделатьСкриншот = ПолучитьЗначениеПереданногоПараметра(СтрутктураJSON,"КомандаСделатьСкриншот");
		Если ЗначениеЗаполнено(ЗнКомандаСделатьСкриншот) Тогда
			Объект.КомандаСделатьСкриншот = ЗнКомандаСделатьСкриншот;
		КонецЕсли;	 
		
		Если Объект.ДелатьСкриншотПриВозникновенииОшибки Тогда
			ЗнКаталогOutputСкриншоты = ПолучитьЗначениеПереданногоПараметра(СтрутктураJSON,"КаталогOutputСкриншоты");
			Объект.КаталогOutputСкриншоты = ЗнКаталогOutputСкриншоты;
		КонецЕсли;	 
		//по скриншотам - окончание
		
		

		
		Объект.ИмяТекущейСборки = ПолучитьЗначениеПереданногоПараметра(СтрутктураJSON,"ИмяСборки");
		
		
		ЗнЗакрытьTestClientПослеЗапускаСценариев = ПолучитьЗначениеПереданногоПараметра(СтрутктураJSON,"ЗакрытьTestClientПослеЗапускаСценариев");
		Если ЗнЗакрытьTestClientПослеЗапускаСценариев = Истина Тогда
			Объект.ЗакрытьTestClientПослеЗапускаСценариев = Истина;
		КонецЕсли;	 
		
		Если Объект.СоздаватьИнструкциюHTML Тогда
			ЗнКаталогOutputИнструкцияHTML = ПолучитьЗначениеПереданногоПараметра(СтрутктураJSON,"КаталогOutputИнструкцияHTML");
			Объект.КаталогOutputИнструкцияHTML = ЗнКаталогOutputИнструкцияHTML;
		КонецЕсли;	 
		
		Если Объект.СоздаватьИнструкциюMarkdown Тогда
			ЗнКаталогOutputИнструкцияMarkdown = ПолучитьЗначениеПереданногоПараметра(СтрутктураJSON,"КаталогOutputИнструкцияMarkdown");
			Объект.КаталогOutputИнструкцияMarkdown = ЗнКаталогOutputИнструкцияMarkdown;
		КонецЕсли;	 
		
		Если Объект.СоздаватьИнструкциюВидео Тогда
			ЗнКаталогOutputИнструкцияВидео = ПолучитьЗначениеПереданногоПараметра(СтрутктураJSON,"КаталогOutputИнструкцияВидео");
			Объект.КаталогOutputИнструкцияВидео = ЗнКаталогOutputИнструкцияВидео;
		КонецЕсли;	 
		
		ЗнКаталогСкриптовСборкиВидео = ПолучитьЗначениеПереданногоПараметра(СтрутктураJSON,"КаталогСкриптовСборкиВидео");
		Если ЗначениеЗаполнено(ЗнКаталогСкриптовСборкиВидео) Тогда
			Объект.КаталогСкриптовСборкиВидео = ЗнКаталогСкриптовСборкиВидео;
		КонецЕсли;	 
		
		
		//для отчета xUnit
		ЗнДелатьОтчетВФорматеxUnit = ПолучитьЗначениеПереданногоПараметра(СтрутктураJSON,"ДелатьОтчетВФорматеxUnit");
		Если ЗнДелатьОтчетВФорматеxUnit = Истина Тогда
			ОпределилиКаталогxUnit = Ложь;
			ЗнКаталогOutputxUnit = ПолучитьЗначениеПереданногоПараметра(СтрутктураJSON,"КаталогOutputxUnit");
			Если ЗначениеЗаполнено(ЗнКаталогOutputxUnit) Тогда
				Файл = Новый Файл(ЗнКаталогOutputxUnit);
				Если Не ФайлСуществуетКомандаСистемы(Файл.ПолноеИмя) Тогда
					Стр = "В параметрах JSON передан несуществующий каталог для отчета КаталогOutputxUnit!";
					СделатьСообщение(Стр);
					ЗаписатьЛогВЖРОшибка("VanessaBehavior.ЗапускВРежимеКоманднойСтроки",Стр);
					Возврат;
				КонецЕсли;	 
				Объект.КаталогOutputxUnit      = ЗнКаталогOutputxUnit;
				Объект.ДелатьОтчетВФорматеxUnit = Истина;
				ОпределилиКаталогxUnit         = Истина;
			КонецЕсли;	 
			
			ЗнДобавлятьКИмениСценарияУловияВыгрузки = ПолучитьЗначениеПереданногоПараметра(СтрутктураJSON,"ДобавлятьКИмениСценарияУловияВыгрузки");
			Если ЗнДобавлятьКИмениСценарияУловияВыгрузки = Истина Тогда
				Объект.ДобавлятьКИмениСценарияУловияВыгрузки = Истина;
			КонецЕсли;	 
			
			ЗнВыгружатьСтатусВыполненияСценариевВФайл = ПолучитьЗначениеПереданногоПараметра(СтрутктураJSON,"ВыгружатьСтатусВыполненияСценариевВФайл");
			Если ЗнВыгружатьСтатусВыполненияСценариевВФайл = Истина Тогда
				Объект.ВыгружатьСтатусВыполненияСценариевВФайл = Истина;
			КонецЕсли;	 
			
			ЗнПутьКФайлуДляВыгрузкиСтатусаВыполненияСценариев = ПолучитьЗначениеПереданногоПараметра(СтрутктураJSON,"ПутьКФайлуДляВыгрузкиСтатусаВыполненияСценариев");
			Если ЗнПутьКФайлуДляВыгрузкиСтатусаВыполненияСценариев <> Неопределено Тогда
				Объект.ПутьКФайлуДляВыгрузкиСтатусаВыполненияСценариев = ЗнПутьКФайлуДляВыгрузкиСтатусаВыполненияСценариев;
			КонецЕсли;	 
			
			ЗнКаталогOutputxUnitБазовый = ПолучитьЗначениеПереданногоПараметра(СтрутктураJSON,"КаталогOutputxUnitБазовый");
			Если ЗначениеЗаполнено(ЗнКаталогOutputxUnitБазовый) Тогда
				Файл = Новый Файл(ЗнКаталогOutputxUnitБазовый);
				Если Не ФайлСуществуетКомандаСистемы(Файл.ПолноеИмя) Тогда
					//Стр = "В параметрах JSON передан несуществующий каталог для отчета КаталогOutputxUnitБазовый!";
					//СделатьСообщение(Стр);
					//ЗаписатьЛогВЖРОшибка("VanessaBehavior.ЗапускВРежимеКоманднойСтроки",Стр);
					//Возврат;
					
					СоздатьКаталогКомандаСистемы(ЗнКаталогOutputxUnitБазовый);
				КонецЕсли;	 
				
				СисИнфо = Новый СистемнаяИнформация; 
				ВерсияПриложения = СисИнфо.ВерсияПриложения;
				
				ЗнКаталогOutputxUnitБазовый = ДополнитьСлешВПуть(ЗнКаталогOutputxUnitБазовый) + "\" + ПолучитьЗначениеПереданногоПараметра(СтрутктураJSON,"ИмяСборки");
				ОчиститьСодержимоеКаталога(ЗнКаталогOutputxUnitБазовый);
				ФайлПроверкаСуществования = Новый Файл(ЗнКаталогOutputxUnitБазовый);
				Если НЕ ФайлСуществуетКомандаСистемы(ФайлПроверкаСуществования.ПолноеИмя) Тогда
					СоздатьКаталогКомандаСистемы(ЗнКаталогOutputxUnitБазовый);
					
					ФайлПроверкаСуществования = Новый Файл(ЗнКаталогOutputxUnitБазовый);
					Если НЕ ФайлСуществуетКомандаСистемы(ФайлПроверкаСуществования.ПолноеИмя) Тогда
						СделатьСообщение("Не смог создать каталог для отчета xUnit: " + ЗнКаталогOutputxUnitБазовый);
						Возврат;
					КонецЕсли;	 
				КонецЕсли;	 
				
				Объект.КаталогOutputxUnit      = ЗнКаталогOutputxUnitБазовый;
				Объект.ДелатьОтчетВФорматеxUnit = Истина;
				ОпределилиКаталогxUnit         = Истина;
			КонецЕсли;	 
			
			Если НЕ ОпределилиКаталогxUnit Тогда
				СделатьСообщение("Не смог из переданных параметров JSON определить каталог отчета xUnit!");
				Возврат;
			КонецЕсли;	 
		КонецЕсли;	 	
		
		
		
		
		//для отчета Allure
		ЗнДелатьОтчетВФорматеАллюр = ПолучитьЗначениеПереданногоПараметра(СтрутктураJSON,"ДелатьОтчетВФорматеАллюр");
		Если ЗнДелатьОтчетВФорматеАллюр = Истина Тогда
			ОпределилиКаталогAllure = Ложь;
			ЗнКаталогOutputAllure = ПолучитьЗначениеПереданногоПараметра(СтрутктураJSON,"КаталогOutputAllure");
			Если ЗначениеЗаполнено(ЗнКаталогOutputAllure) Тогда
				УдалитьКаталогКомандаСистемы(ЗнКаталогOutputAllure);
				
				Файл = Новый Файл(ЗнКаталогOutputAllure);
				Если Не ФайлСуществуетКомандаСистемы(Файл.ПолноеИмя) Тогда
					//Стр = "В параметрах JSON передан несуществующий каталог для отчета КаталогOutputAllure!";
					//СделатьСообщение(Стр);
					//ЗаписатьЛогВЖРОшибка("VanessaBehavior.ЗапускВРежимеКоманднойСтроки",Стр);
					//Возврат;
					
					СоздатьКаталогКомандаСистемы(ЗнКаталогOutputAllure);
				КонецЕсли;	 
				Объект.КаталогOutputAllure      = ЗнКаталогOutputAllure;
				Объект.ДелатьОтчетВФорматеАллюр = Истина;
				ОпределилиКаталогAllure         = Истина;
			КонецЕсли;	 
			
			ЗнДобавлятьКИмениСценарияУловияВыгрузки = ПолучитьЗначениеПереданногоПараметра(СтрутктураJSON,"ДобавлятьКИмениСценарияУловияВыгрузки");
			Если ЗнДобавлятьКИмениСценарияУловияВыгрузки = Истина Тогда
				Объект.ДобавлятьКИмениСценарияУловияВыгрузки = Истина;
			КонецЕсли;	 
			
			ЗнВыгружатьСтатусВыполненияСценариевВФайл = ПолучитьЗначениеПереданногоПараметра(СтрутктураJSON,"ВыгружатьСтатусВыполненияСценариевВФайл");
			Если ЗнВыгружатьСтатусВыполненияСценариевВФайл = Истина Тогда
				Объект.ВыгружатьСтатусВыполненияСценариевВФайл = Истина;
			КонецЕсли;	 
			
			ЗнПутьКФайлуДляВыгрузкиСтатусаВыполненияСценариев = ПолучитьЗначениеПереданногоПараметра(СтрутктураJSON,"ПутьКФайлуДляВыгрузкиСтатусаВыполненияСценариев");
			Если ЗнПутьКФайлуДляВыгрузкиСтатусаВыполненияСценариев <> Неопределено Тогда
				Объект.ПутьКФайлуДляВыгрузкиСтатусаВыполненияСценариев = ЗнПутьКФайлуДляВыгрузкиСтатусаВыполненияСценариев;
			КонецЕсли;	 
			
			ЗнКаталогOutputAllureБазовый = ПолучитьЗначениеПереданногоПараметра(СтрутктураJSON,"КаталогOutputAllureБазовый");
			Если ЗначениеЗаполнено(ЗнКаталогOutputAllureБазовый) Тогда
				Файл = Новый Файл(ЗнКаталогOutputAllureБазовый);
				Если Не ФайлСуществуетКомандаСистемы(Файл.ПолноеИмя) Тогда
					//Стр = "В параметрах JSON передан несуществующий каталог для отчета КаталогOutputAllureБазовый!";
					//СделатьСообщение(Стр);
					//ЗаписатьЛогВЖРОшибка("VanessaBehavior.ЗапускВРежимеКоманднойСтроки",Стр);
					//Возврат;
					
					СоздатьКаталогКомандаСистемы(ЗнКаталогOutputAllureБазовый);
				КонецЕсли;	 
				
				СисИнфо = Новый СистемнаяИнформация; 
				ВерсияПриложения = СисИнфо.ВерсияПриложения;
				
				Если ПолучитьЗначениеПереданногоПараметра(СтрутктураJSON,"СоздаватьПодкаталогВКаталогеAllureДляЭтойСборки") = Истина Тогда
					ЗнКаталогOutputAllureБазовый = ЗнКаталогOutputAllureБазовый + "\" + ПолучитьЗначениеПереданногоПараметра(СтрутктураJSON,"ИмяСборки");
				КонецЕсли;	 
				
				
				ОчиститьСодержимоеКаталога(ЗнКаталогOutputAllureБазовый);
				ФайлПроверкаСуществования = Новый Файл(ЗнКаталогOutputAllureБазовый);
				Если НЕ ФайлСуществуетКомандаСистемы(ФайлПроверкаСуществования.ПолноеИмя) Тогда
					СоздатьКаталогКомандаСистемы(ЗнКаталогOutputAllureБазовый);
					
					ФайлПроверкаСуществования = Новый Файл(ЗнКаталогOutputAllureБазовый);
					Если НЕ ФайлСуществуетКомандаСистемы(ФайлПроверкаСуществования.ПолноеИмя) Тогда
						СделатьСообщение("Не смог создать каталог для отчета Allure: " + ЗнКаталогOutputAllureБазовый);
						Возврат;
					КонецЕсли;	 
				КонецЕсли;	 
				
				Объект.КаталогOutputAllure      = ЗнКаталогOutputAllureБазовый;
				Объект.ДелатьОтчетВФорматеАллюр = Истина;
				ОпределилиКаталогAllure         = Истина;
			КонецЕсли;	 
			
			Если НЕ ОпределилиКаталогAllure Тогда
				СделатьСообщение("Не смог из переданных параметров JSON определить каталог отчета Allure!");
				Возврат;
			КонецЕсли;	 
		КонецЕсли;	 
		
		ВыполнитьСценарии = ПолучитьЗначениеПереданногоПараметра(СтрутктураJSON,"ВыполнитьСценарии");
		Если ВыполнитьСценарии = Истина Тогда
			ЗнЗавершитьРаботуСистемы = ПолучитьЗначениеПереданногоПараметра(СтрутктураJSON,"ЗавершитьРаботуСистемы");
			Если ЗнЗавершитьРаботуСистемы = Истина Тогда
				Объект.НадоЗавершитьРаботуСистемыПослеВыполненияВсехСценариев = Истина;
			КонецЕсли;	 
			
			Если ЕстьПоддержкаАсинхронныхВызовов Тогда
				Объект.НадоВыполнитьСценарииПослеЗагрузкиФич = Истина;
				ЗагрузитьФичи();
			Иначе	
				ЗагрузитьФичи();
				ВыполнитьСценарии();
			КонецЕсли;	 
		КонецЕсли;	 
		
	КонецЕсли;	 
	
КонецПроцедуры

&НаСервереБезКонтекста
Функция ЕстьКонстантаВКонфигурацииСервер(ИмяКонстанты)
	Зн = Метаданные.Константы.Найти(ИмяКонстанты);
	Если Зн = Неопределено Тогда
		Возврат Ложь;
	КонецЕсли;	 
	
	Возврат Истина;
КонецФункции	

&НаКлиенте
Процедура УстановитьВидимостьФлагаПроверкаРаботыVanessaBehaviorВРежимеTestClient()
	ЕстьКонстантаВКонфигурации = ЕстьКонстантаВКонфигурацииСервер("ПутьКVanessaBehavior");
	Элементы.ПроверкаРаботыVanessaBehaviorВРежимеTestClient.Видимость = ЕстьКонстантаВКонфигурации;
КонецПроцедуры

&НаКлиенте
Процедура УстановитьВидимостьСтраницыСлужебная()
	ЕстьКонстантаВКонфигурации = ЕстьКонстантаВКонфигурацииСервер("ПутьКVanessaBehavior");
	Элементы.ГруппаСлужебная.Видимость = Объект.ПроверкаРаботыVanessaBehaviorВРежимеTestClient И ЕстьКонстантаВКонфигурации;
КонецПроцедуры


&НаКлиенте
Процедура УстановитьВидимостьКолонокДереваВСлужебномРежиме()
	ЕстьКонстантаВКонфигурации = ЕстьКонстантаВКонфигурацииСервер("ПутьКVanessaBehavior");
	Элементы.ГруппаСлужебная.Видимость = Объект.ПроверкаРаботыVanessaBehaviorВРежимеTestClient И ЕстьКонстантаВКонфигурации;
	ЭтаФорма.Элементы.ДеревоТестовСтатус.Видимость = Объект.ПроверкаРаботыVanessaBehaviorВРежимеTestClient И ЕстьКонстантаВКонфигурации;;
КонецПроцедуры

&НаКлиенте
Процедура УстановитьВидимостьСлужебныхЭлементов()
	УстановитьВидимостьФлагаПроверкаРаботыVanessaBehaviorВРежимеTestClient();
	УстановитьВидимостьСтраницыСлужебная();
	УстановитьВидимостьКолонокДереваВСлужебномРежиме();
КонецПроцедуры

&НаКлиенте
Процедура МаксимизироватьФорму()
	Если Объект.РежимСамотестирования Тогда
		Возврат;
	КонецЕсли;	 
	
	WSHShell = Новый COMОбъект("WScript.Shell");
    WSHShell.SendKeys("%");
    WSHShell.SendKeys("{LEFT}{LEFT}{ENTER}");  	
КонецПроцедуры

&НаКлиенте
Процедура ПослеОткрытияФормы()
	//Если Не ЭтоLinux Тогда
	//	МаксимизироватьФорму();
	//КонецЕсли;	 
	
	
	ЗапускВРежимеКоманднойСтроки();
	
	Если НЕ Объект.ЗапускИзКоманднойСтроки Тогда
		Если СокрЛП(Объект.КаталогФич) <> "" Тогда
			ЗагрузитьФичи();
		КонецЕсли;	 
	КонецЕсли;	 
КонецПроцедуры

&НаКлиенте
Процедура ПриОткрытии(Отказ)
	УстановитьВидимостьСлужебныхЭлементов();
	
	УстановитьКраткийЗаголовокПриложения("Vanessa-behavior");
	
	ЭтоLinux = Ложь;
	СисИнфо = Новый СистемнаяИнформация;
	Если Найти(Строка(СисИнфо.ТипПлатформы), "Linux")>0 Тогда 
		ЭтоLinux = Истина;
	КонецЕсли;
	
	
	
	
	Объект.ВыполнятьШагиАссинхронно = Истина;
	Объект.СохранятьКонтекстыПередВыполнениемШагов = Истина;
	
	
	ОбъектКонтекстСохраняемый = Новый Структура;
	
	ЗаполнитьКонтекстноеМеню();
	ЗаполнитьКаталогИнструментовЕслиОнПустой();
	
	МассивСнипетовПрерывающихЗаписьСценария = ПолучитьМассивСнипетовПрерывающихЗаписьСценария();
	
	ВосстановитьНастройкиКлиент();
	
	
	Объект.ИнтервалВыполненияШага = Объект.ИнтервалВыполненияШагаЗаданныйПользователем;
	Если Объект.ИнтервалВыполненияШага = 0 Тогда
		Объект.ИнтервалВыполненияШага = 0.1;
		Объект.ИнтервалВыполненияШагаЗаданныйПользователем = 0.1;
	КонецЕсли;	 
	
	
	
	КаталогФич          = Объект.КаталогФич;
	КаталогИнструментов = Объект.КаталогИнструментов;
	
	ОбновитьКнопкуЗагрузитьФичи();
	
	
	
	ЭтаФорма.Заголовок = ПолучитьВерсиюОбработкиСервер();
	
	Объект.КаталогиБиблиотек.ТипЗначения     = Новый ОписаниеТипов("Строка");
	Объект.СписокТеговИсключение.ТипЗначения = Новый ОписаниеТипов("Строка");
	Объект.СписокТеговОтбор.ТипЗначения      = Новый ОписаниеТипов("Строка");

	ЭтаФорма.ТекущийЭлемент = Элементы.ДеревоТестов;
	
	ПодключитьОбработчикОжидания("ПослеОткрытияФормы",0.1,Истина);
	
	
КонецПроцедуры

&НаКлиенте
Процедура ПриЗакрытии()
	ОтключитьОбработчикОжидания("ОпросЭлементовФормTestClient");
	Если НЕ ЭтоЗапускВРежимеБезЗагрукиНастроек Тогда
		СохранитьНастройки();
	КонецЕсли;	 
КонецПроцедуры

&НаКлиенте
Процедура ЗагрузитьОднуФичу(Команда)
	Объект.текЗначениеОперации = "ЗагрузитьОднуФичу";
	ОбновитьКнопкуЗагрузитьФичи();
	
	Объект.РежимВыполненияСценарияСВыбранногоШага = Ложь;
	СтрокаШагаСКоторогоНадоВыполнятьСценарий      = Неопределено;
	МассивСостоянияКонтекстовДоВыполненияШага     = Новый Массив;
	
	ЗагрузитьТестыЗагрузитьОднуФичу();
КонецПроцедуры

&НаКлиенте
Процедура ОбработатьВыборФайла(ВыбранныеФайлы,ДополнительныеПараметры) Экспорт
	Если ВыбранныеФайлы = Неопределено Тогда
		Возврат;
	КонецЕсли;	 
	
	Объект.КаталогФич = ВыбранныеФайлы[0];
	ЗагрузитьФичи();
КонецПроцедуры

&НаКлиенте
Процедура ЗагрузитьТестыЗагрузитьОднуФичу()
	ОчиститьСообщения();
	
	Режим = РежимДиалогаВыбораФайла.Открытие;
	ДиалогОткрытияФайла = Новый ДиалогВыбораФайла(Режим);
	ДиалогОткрытияФайла.Заголовок = "Выберите feature файл";
	ДиалогОткрытияФайла.Фильтр = "Фича файл (*.feature)|*.feature";
	Если ЕстьПоддержкаАсинхронныхВызовов Тогда
		ОписаниеОповещения = Вычислить("Новый ОписаниеОповещения(""ОбработатьВыборФайла"", ЭтаФорма)");
		Выполнить("ДиалогОткрытияФайла.Показать(ОписаниеОповещения)");
	Иначе	
		Если ДиалогОткрытияФайла.Выбрать() Тогда
			Объект.КаталогФич = ДиалогОткрытияФайла.ПолноеИмяФайла;
		Иначе
			Возврат;
		КонецЕсли;
		ЗагрузитьФичи();
	КонецЕсли;  
	
КонецПроцедуры

&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
	ЕстьПоддержкаНемодальныхФорм    = УзнатьЕстьПоддержкаНемодальныхФорм();
	ЕстьПоддержкаАсинхронныхВызовов = УзнатьЕстьПоддержкаАсинхронныхВызовов();
	
	ОбъектНаСервере = РеквизитФормыВЗначение("Объект");
	СтатусыРезультатаТестирования = ОбъектНаСервере.СтатусыРезультатаТестирования;
	
КонецПроцедуры

&НаКлиенте
Процедура Перезагрузить(Команда)
	ЗагрузитьФичи();
КонецПроцедуры

&НаКлиенте
Процедура СделатьПараметрыКорректными()
	Если Найти(Прав(Объект.КаталогИнструментов,1), "\/") > 0 Тогда
		Объект.КаталогИнструментов = Лев(Объект.КаталогИнструментов,СтрДлина(Объект.КаталогИнструментов)-1);
	КонецЕсли; 
	Если Найти(Прав(Объект.КаталогOutputИнструкцияHTML,1), "\/") > 0 Тогда
		Объект.КаталогOutputИнструкцияHTML = Лев(Объект.КаталогOutputИнструкцияHTML,СтрДлина(Объект.КаталогOutputИнструкцияHTML)-1);
	КонецЕсли; 
	Если Найти(Прав(Объект.КаталогOutputИнструкцияHTML,1), "\/") > 0 Тогда
		Объект.КаталогOutputИнструкцияMarkdown = Лев(Объект.КаталогOutputИнструкцияMarkdown,СтрДлина(Объект.КаталогOutputИнструкцияMarkdown)-1);
	КонецЕсли; 
	Если Найти(Прав(Объект.КаталогOutputСкриншоты,1), "\/") > 0 Тогда
		Объект.КаталогOutputСкриншоты = Лев(Объект.КаталогOutputСкриншоты,СтрДлина(Объект.КаталогOutputСкриншоты)-1);
	КонецЕсли; 
	Если Найти(Прав(Объект.КаталогOutputИнструкцияВидео,1), "\/") > 0 Тогда
		Объект.КаталогOutputИнструкцияВидео = Лев(Объект.КаталогOutputИнструкцияВидео,СтрДлина(Объект.КаталогOutputИнструкцияВидео)-1);
	КонецЕсли; 
	Если Найти(Прав(Объект.КаталогСкриптовСборкиВидео,1), "\/") > 0 Тогда
		Объект.КаталогСкриптовСборкиВидео = Лев(Объект.КаталогСкриптовСборкиВидео,СтрДлина(Объект.КаталогСкриптовСборкиВидео)-1);
	КонецЕсли; 
КонецПроцедуры

&НаСервере
Процедура ОчиститьПоляВДеревеДляПостроенияОтчетов(Дерево)
	Для каждого СтрСтроки Из Дерево.Строки Цикл
		СтрСтроки.Статус     = "";
		Если СтрСтроки.Шаг = Истина Тогда
			СтрСтроки.ТипКартинки = 3;
		КонецЕсли;	 
		
		ОчиститьПоляВДеревеДляПостроенияОтчетов(СтрСтроки);
		
	КонецЦикла;
КонецПроцедуры

&НаСервере
Процедура ОчиститьПоляВДеревеДляПостроенияОтчетовСервер()
	ОбъектСервер = РеквизитФормыВЗначение("Объект");
	
	Дерево = ОбъектСервер.ДеревоТестов;
	ОчиститьПоляВДеревеДляПостроенияОтчетов(Дерево);
	
	ЗначениеВРеквизитФормы(ОбъектСервер,"Объект");
КонецПроцедуры

&НаСервере
Функция ЭтоСценарий_SceanrioOutline(СтрокаДерева)
	Для каждого СтрСтроки Из СтрокаДерева.Строки Цикл
		Если СтрСтроки.Примеры = Истина Тогда
			Возврат Истина;
		КонецЕсли;	 
	КонецЦикла;
	
	Возврат Ложь;
КонецФункции

&НаСервере
Процедура ДобавитьШагиДляВыполненияСценария(Шаги,ДеревоСтроки,СтрокаДерева,СтрокаСценария,ЭтоШагКонтекста)
	Для каждого СтрСтроки Из ДеревоСтроки Цикл
		Если СтрСтроки.Шаг = Истина Тогда
			СтруктураШага = ПолучитьСтруктуруШага(СтрСтроки,СтрокаДерева,СтрокаДерева,ЭтоШагКонтекста);
			Шаги.Добавить(СтруктураШага);
		ИначеЕсли СтрСтроки.ШагСценарий = Истина Тогда
			ДобавитьШагиДляВыполненияСценария(Шаги,СтрСтроки.Строки,СтрокаДерева,СтрокаСценария,ЭтоШагКонтекста)
		ИначеЕсли СтрСтроки.Область = Истина Тогда
			ДобавитьШагиДляВыполненияСценария(Шаги,СтрСтроки.Строки,СтрокаДерева,СтрокаСценария,ЭтоШагКонтекста)
		КонецЕсли;	 
	КонецЦикла;
КонецПроцедуры

&НаСервере
Процедура ДобавитьСценарийАутлайн(СтрокаДерева,МассивСценариевДляВыполнения,ТекПример = Неопределено,ДопПараметры)
	//получим сами именнованные параметры
	
	ИменаПараметров = Неопределено;
	СтрокаПримеров  = Неопределено;
	Для каждого СтрСтроки Из СтрокаДерева.Строки Цикл
		Если СтрСтроки.Примеры = Истина Тогда
			ИменаПараметров = СтрСтроки.ИменованныеПараметры;
			СтрокаПримеров = СтрСтроки;
		КонецЕсли; 
	КонецЦикла;
	
	Если ИменаПараметров = Неопределено Тогда
		СтрОшибки = "Не смог найти у сценария " + СтрокаДерева.Имя + " имена изменяемых параметров!";
		Сообщить(СтрОшибки);
		ВызватьИсключение СтрОшибки;
	КонецЕсли; 
	
	
	Ном = 0;
	Для каждого СтрСтрокаПримеров Из СтрокаПримеров.Строки Цикл
		Ном = Ном + 1;
		Если Ном = 1 Тогда
			//в первой строке лежат имена параметров
			Продолжить;
		КонецЕсли; 
		
		Если ТекПример <> Неопределено Тогда
			Если СтрСтрокаПримеров <> ТекПример Тогда
				Продолжить;
			КонецЕсли; 
		КонецЕсли; 
		
		СтруктураПараметровСценария = Новый Структура;
		СтруктураПараметровСценария.Вставить("Имя",СтрокаДерева.Имя + " (Пример №" + (Ном-1) + ")");
		СтруктураПараметровСценария.Вставить("СтрокаДерева",СтрСтрокаПримеров.ИДСтроки);
		СтруктураПараметровСценария.Вставить("ИмяФичи",ДопПараметры.ИмяФичи);
		СтруктураПараметровСценария.Вставить("ПолныйПутьКФиче",ДопПараметры.ПолныйПутьКФиче);
		
		
		Шаги = Новый Массив;
		
		Если СтрокаДерева.Родитель.Строки[0].ЭтоКонтекст = Истина Тогда //значит надо добавить шаги контекста к нашим шагам
			ДобавитьШагиДляВыполненияСценария(Шаги,СтрокаДерева.Родитель.Строки[0].Строки,СтрокаДерева,СтрСтрокаПримеров,Истина);
			//Для каждого СтрСтроки Из СтрокаДерева.Родитель.Строки[0].Строки Цикл
			//	СтруктураШага = ПолучитьСтруктуруШага(СтрСтроки,СтрокаДерева,СтрСтрокаПримеров);
			//	Шаги.Добавить(СтруктураШага);
			//КонецЦикла;
		КонецЕсли;	 
		
		
		ДобавитьШагиДляВыполненияСценария(Шаги,СтрСтрокаПримеров.Строки,СтрокаДерева,СтрСтроки.Родитель,Ложь);
		//Для каждого СтрСтроки Из СтрСтрокаПримеров.Строки Цикл
		//	СтруктураШага = ПолучитьСтруктуруШага(СтрСтроки,СтрокаДерева,СтрСтроки.Родитель);
		//	Шаги.Добавить(СтруктураШага);
		//КонецЦикла;
		
		
		
		
		Если ДопПараметры.РежимВыполненияСценарияСВыбранногоШага Тогда
			МассивДляУдаления = Новый Массив;
			Ном = -1;
			Для каждого Шаг Из Шаги Цикл
				Ном = Ном + 1;
				Если Шаг.СтрокаШага = ДопПараметры.ИдСтрокиШагаСКоторогоВыполнятьСценарий Тогда
					Прервать;
				КонецЕсли;	 
				
				МассивДляУдаления.Добавить(Ном);
			КонецЦикла;
			
			
			Для Ккк = 0 По МассивДляУдаления.Количество()-1 Цикл
				ИД = МассивДляУдаления.Количество()-1 - Ккк;
				Ном = МассивДляУдаления[ИД];
				Шаги.Удалить(Ном);
			КонецЦикла;
		КонецЕсли;	 
		
		
		
		СтруктураПараметровСценария.Вставить("Шаги",Шаги);
		МассивСценариевДляВыполнения.Добавить(СтруктураПараметровСценария);
	КонецЦикла;

КонецПроцедуры

&НаСервере
Функция ПолучитьСтруктуруШага(СтрСтроки,СтрокаДерева,СтрокаСценария,ЭтоШагКонтекста)
	СтруктураШага = Новый Структура;
	СтруктураШага.Вставить("Имя",СтрСтроки.Имя);
	СтруктураШага.Вставить("ЗначенияПараметров",СтрСтроки.ЗначенияПараметров);
	СтруктураШага.Вставить("АдресСнипета",СтрСтроки.АдресСнипета);
	СтруктураШага.Вставить("СтрокаРеальнойПроцедуры",СтрСтроки.СтрокаРеальнойПроцедуры);
	СтруктураШага.Вставить("Снипет",СтрСтроки.Снипет);
	СтруктураШага.Вставить("ИмяСценария",СтрокаДерева.Имя);
	СтруктураШага.Вставить("СтрокаСценария",СтрокаСценария.ИДСтроки);
	СтруктураШага.Вставить("СтрокаШага",СтрСтроки.ИДСтроки);
	СтруктураШага.Вставить("ШагСчитаетсяУпавшим",Ложь);
	СтруктураШага.Вставить("ЭтоШагКонтекста",ЭтоШагКонтекста);
	СтруктураШага.Вставить("ШагСПараметрамиВТаблице",СтрСтроки.ШагСПараметрамиВТаблице);
	СтруктураШага.Вставить("ПараметрыТаблицы",Неопределено);
	
	Если СтрСтроки.ШагСПараметрамиВТаблице = Истина Тогда
		ПараметрыТаблицы = Новый Массив;
		Для каждого ПодчиненнаяСтрока Из СтрСтроки.Строки Цикл
			ПараметрыТаблицы.Добавить(ПодчиненнаяСтрока.Имя);
		КонецЦикла;
		СтруктураШага.Вставить("ПараметрыТаблицы",ПараметрыТаблицы);
	КонецЕсли;	 
	
	Возврат СтруктураШага;
КонецФункции

&НаСервере
Процедура ДобавитьОбычныйСценарий(СтрокаДерева,МассивСценариевДляВыполнения,ДопПараметры)
	Если СтрокаДерева.ЭтоКонтекст = Истина Тогда
		Возврат;
	КонецЕсли;	 
	
	СтруктураПараметров = Новый Структура;
	СтруктураПараметров.Вставить("Имя",СтрокаДерева.Имя);
	СтруктураПараметров.Вставить("СтрокаДерева",СтрокаДерева.ИдСтроки);
	СтруктураПараметров.Вставить("ИмяФичи",ДопПараметры.ИмяФичи);
	СтруктураПараметров.Вставить("ПолныйПутьКФиче",ДопПараметры.ПолныйПутьКФиче);
	
	Шаги = Новый Массив;
	
	
	Если СтрокаДерева.Родитель.Строки[0].ЭтоКонтекст = Истина Тогда //значит надо добавить шаги контекста к нашим шагам
		ДобавитьШагиДляВыполненияСценария(Шаги,СтрокаДерева.Родитель.Строки[0].Строки,СтрокаДерева,СтрокаДерева,Истина);
		//Для каждого СтрСтроки Из СтрокаДерева.Родитель.Строки[0].Строки Цикл
		//	СтруктураШага = ПолучитьСтруктуруШага(СтрСтроки,СтрокаДерева,СтрокаДерева);
		//	Шаги.Добавить(СтруктураШага);
		//КонецЦикла;
	КонецЕсли;	 
	
	ДобавитьШагиДляВыполненияСценария(Шаги,СтрокаДерева.Строки,СтрокаДерева,СтрокаДерева,Ложь);
	//Для каждого СтрСтроки Из СтрокаДерева.Строки Цикл
	//	СтруктураШага = ПолучитьСтруктуруШага(СтрСтроки,СтрокаДерева,СтрокаДерева);
	//	Шаги.Добавить(СтруктураШага);
	//КонецЦикла;
	
	Если ДопПараметры.РежимВыполненияСценарияСВыбранногоШага Тогда
		МассивДляУдаления = Новый Массив;
		Ном = -1;
		Для каждого Шаг Из Шаги Цикл
			Ном = Ном + 1;
			Если Шаг.СтрокаШага = ДопПараметры.ИдСтрокиШагаСКоторогоВыполнятьСценарий Тогда
				Прервать;
			КонецЕсли;	 
			
			МассивДляУдаления.Добавить(Ном);
		КонецЦикла;
		
		
		Для Ккк = 0 По МассивДляУдаления.Количество()-1 Цикл
			ИД = МассивДляУдаления.Количество()-1 - Ккк;
			Ном = МассивДляУдаления[ИД];
			Шаги.Удалить(Ном);
		КонецЦикла;
	КонецЕсли;	 
	
	
	СтруктураПараметров.Вставить("Шаги",Шаги);
	МассивСценариевДляВыполнения.Добавить(СтруктураПараметров);
	
КонецПроцедуры

&НаСервере
Процедура ДобавитьСценарийВМассивСценариевДляВыполнения(СтрокаДерева,МассивСценариевДляВыполнения,ДопПараметры)
	
	ЭтоСценариоАутлайн = ЭтоСценарий_SceanrioOutline(СтрокаДерева);
	Если ЭтоСценариоАутлайн Тогда
		//СделатьСообщение("Запуск СценариоАутлайн пока не реализован. " + СтрокаДерева.Имя);
		ДобавитьСценарийАутлайн(СтрокаДерева,МассивСценариевДляВыполнения,,ДопПараметры);
		Возврат;
	КонецЕсли;	 
	
	ДобавитьОбычныйСценарий(СтрокаДерева,МассивСценариевДляВыполнения,ДопПараметры);
КонецПроцедуры

&НаСервере
Процедура ДобавитьСценарииРекурсивно_ВМассивСценариевДляВыполнения(ДеревоСтроки,МассивСценариевДляВыполнения,ТекИДСценария,ДопПараметры)
	Если ТипЗнч(ДеревоСтроки) = Тип("СтрокаДереваЗначений") Тогда
		Если ДеревоСтроки.Фича = Истина Тогда
			ДопПараметры.Вставить("ИмяФичи",ДеревоСтроки.Имя);
			ДопПараметры.Вставить("ПолныйПутьКФиче",ДеревоСтроки.ПолныйПуть);
		КонецЕсли;	
		
		Если ДеревоСтроки.Сценарий = Истина Тогда
			ДобавитьСценарийВМассивСценариевДляВыполнения(ДеревоСтроки,МассивСценариевДляВыполнения,ДопПараметры);
		ИначеЕсли ДеревоСтроки.Пример = Истина Тогда
			ДобавитьСценарийАутлайн(ДеревоСтроки.Родитель.Родитель,МассивСценариевДляВыполнения,ДеревоСтроки,ДопПараметры)
		КонецЕсли; 
	Иначе	
		Для каждого СтрДеревоСтроки Из ДеревоСтроки Цикл
			Если СтрДеревоСтроки.Фича = Истина Тогда
				ДопПараметры.Вставить("ИмяФичи",СтрДеревоСтроки.Имя);
				ДопПараметры.Вставить("ПолныйПутьКФиче",СтрДеревоСтроки.ПолныйПуть);
			КонецЕсли;	
			
			Если СтрДеревоСтроки.Сценарий = Истина Тогда
				Если ТекИДСценария <> Неопределено Тогда
					Если СтрДеревоСтроки.ИдСтроки = ТекИДСценария Тогда
						ДобавитьСценарийВМассивСценариевДляВыполнения(СтрДеревоСтроки,МассивСценариевДляВыполнения,ДопПараметры);
					КонецЕсли;	 
				Иначе	
					ДобавитьСценарийВМассивСценариевДляВыполнения(СтрДеревоСтроки,МассивСценариевДляВыполнения,ДопПараметры);
				КонецЕсли;	 
			Иначе	
				ДобавитьСценарииРекурсивно_ВМассивСценариевДляВыполнения(СтрДеревоСтроки.Строки,МассивСценариевДляВыполнения,ТекИДСценария,ДопПараметры);
			КонецЕсли;	 
		КонецЦикла;
	КонецЕсли; 
КонецПроцедуры

&НаСервере
Процедура ПроставитьИДРекурсивно(ДеревоСтроки,ИД,МассивСтрокДереваДанныеФормы,МассивИменКонтекстовОбработок,ТзнТаблицаИзвестныхStepDefinition,ДопПараметры,ЕстьСвояEPFУФичи = Неопределено)
	ЭтоLinux = Ложь;
	СисИнфо = Новый СистемнаяИнформация;
	Если Найти(Строка(СисИнфо.ТипПлатформы), "Linux")>0 Тогда 
		ЭтоLinux = Истина;
	КонецЕсли;
	
	Для каждого СтрокаДерева Из ДеревоСтроки Цикл
		
		Если СтрокаДерева.Фича = Истина Тогда
			ФайлФичи = Новый Файл(СтрокаДерева.ПолныйПуть);
			ФайлEPF  = ФайлФичи.Путь + "step_definitions" +?(ЭтоLinux, "/", "\") + ФайлФичи.ИмяБезРасширения + ".epf";
			СтрТзнТаблицаИзвестныхStepDefinition = МассивИменКонтекстовОбработок.Найти(ФайлEPF);
			ЕстьСвояEPFУФичи = Истина;
			Если СтрТзнТаблицаИзвестныхStepDefinition = Неопределено Тогда
				ЕстьСвояEPFУФичи = Ложь;
			КонецЕсли;  
		КонецЕсли;  
		СтрокаДерева.ФичаИмеетСвоюEPF = ЕстьСвояEPFУФичи;
		
		СтрокаДерева.ИДСтроки = ИД;
		Если ДопПараметры.РежимВыполненияСценарияСВыбранногоШага Тогда
			Если СтрокаДерева.ИДСтроки = ДопПараметры.ИдСтрокиШагаСКоторогоВыполнятьСценарий Тогда
				СтрокаДерева.ВыполнятьСценарийСЭтогоШага = Истина;
			КонецЕсли;	 
		КонецЕсли;	 
		МассивСтрокДереваДанныеФормы.Добавить();//просто добавим пустой элемент
		ИД = ИД + 1;
		ПроставитьИДРекурсивно(СтрокаДерева.Строки,ИД,МассивСтрокДереваДанныеФормы,МассивИменКонтекстовОбработок,ТзнТаблицаИзвестныхStepDefinition,ДопПараметры,ЕстьСвояEPFУФичи);
	КонецЦикла;
КонецПроцедуры

&НаСервере
Процедура ЗаполнитьИДСтрокиВДереве(Дерево,МассивСтрокДереваДанныеФормы,МассивИменКонтекстовОбработок,ТзнТаблицаИзвестныхStepDefinition,ДопПараметры)
	Ид = 0;
	ПроставитьИДРекурсивно(Дерево.Строки,ИД,МассивСтрокДереваДанныеФормы,МассивИменКонтекстовОбработок,ТзнТаблицаИзвестныхStepDefinition,ДопПараметры);
КонецПроцедуры

&НаСервере
Процедура ЗаполнитьМассивСценариевДляВыполненияСервер(МассивСценариевДляВыполнения,МассивСтрокДереваДанныеФормы,ТекИДСценария,МассивИменКонтекстовОбработок,ДопПараметры)
	ДеревоФорма = Объект.ДеревоТестов;
	
	ОбъектСервер = РеквизитФормыВЗначение("Объект");
	
	ТзнТаблицаИзвестныхStepDefinition = РеквизитФормыВЗначение("ТаблицаИзвестныхStepDefinition");
	ЗаполнитьИДСтрокиВДереве(ОбъектСервер.ДеревоТестов,МассивСтрокДереваДанныеФормы,МассивИменКонтекстовОбработок,ТзнТаблицаИзвестныхStepDefinition,ДопПараметры);
	
	ТекСценарий = Неопределено;
	Если ТекСценарий = Неопределено Тогда
		ТекСценарий = ОбъектСервер.ДеревоТестов.Строки;
	КонецЕсли; 
	
	ДобавитьСценарииРекурсивно_ВМассивСценариевДляВыполнения(ТекСценарий,МассивСценариевДляВыполнения,ТекИДСценария,ДопПараметры);
	
	ЗначениеВРеквизитФормы(ОбъектСервер,"Объект");
	
КонецПроцедуры

&НаКлиенте
Процедура ОбработатьСтатусСценария(ИД)
	ИДСтрокиСценария = МассивСценариевДляВыполнения[ИД].СтрокаДерева;
	СтрокаСценария   = МассивСтрокДереваДанныеФормы[ИДСтрокиСценария];
	
	Если СокрЛП(СтрокаСценария.Статус) <> "" Тогда
		Возврат;
	КонецЕсли;	 
	
	РезультатПрохожденияТестовСценария = ПолучитьРезультатПрохожденияТестовСценария(ИДСтрокиСценария);
	РезультатПрохожденияТестовШагов = РезультатПрохожденияТестовСценария.РезультатПрохожденияТестовШагов;
	
	СценарийВыполнен = Истина;
	СтрокиСценария = СтрокаСценария.ПолучитьЭлементы();
	Для каждого СтрШаг Из РезультатПрохожденияТестовШагов Цикл
		Если СтрШаг.Статус <> "Success" Тогда
			СценарийВыполнен = Ложь;
			Статус = СтрШаг.Статус;
			Прервать;
		КонецЕсли; 
	КонецЦикла;
	
	Если СценарийВыполнен Тогда
		СтрокаСценария.Статус = "Success";
	Иначе	
		СтрокаСценария.Статус = Статус;
	КонецЕсли; 
	
КонецПроцедуры

&НаКлиенте
Процедура ПолучениеКонтекстаОбработки(Результат,АдресХранилища,ВыбранноеИмяФайла,ДополнительныеПараметры) Экспорт
	
КонецПроцедуры

&НаКлиенте
Функция ПреобразоватьКДатеСтроку(Знач Стр) 
	НачСтр = Стр;
	//Зн = Дата(Стр);
	Год   = 0;
	Месяц = 0;
	День  = 0;
	
	Поз  = Найти(Стр,".");
	День = Число(Лев(Стр,Поз-1));
	Стр = Сред(Стр,Поз+1);
	
	Поз   = Найти(Стр,".");
	Месяц = Число(Лев(Стр,Поз-1));
	Стр   = Сред(Стр,Поз+1);
	
	Год   = Число(Стр);
	Если Год < 100 Тогда
		Год = Год + 2000;
	КонецЕсли;
	
	Зн = Дата(Год,Месяц,День);
	
	Зн = Формат(Зн,"ДФ=yyyyMMdd");
	Зн = "'" + Зн + "'";
	
	Возврат Зн;
КонецФункции

&НаКлиенте
Процедура ВызватьМетод(Обработка, Знач ИмяПроцедуры, МассивАргументов)
	Поз = Найти(ИмяПроцедуры,"(");
	Если Поз > 0 Тогда
		ИмяПроцедуры = Лев(ИмяПроцедуры,Поз-1);
	КонецЕсли;	 
	
	Команда = "Обработка." + ИмяПроцедуры + "(";
	
	АргументТаблица = Неопределено;
	
	Если МассивАргументов <> Неопределено Тогда
		Для Ккк = 0 По МассивАргументов.Количество()-1 Цикл
			Элем = МассивАргументов[Ккк];
			Если ТипЗнч(Элем) = Тип("Массив") Тогда
				АргументТаблица = Элем;
				Команда = Команда + "АргументТаблица";
			Иначе	
				Команда = Команда + Элем;
			КонецЕсли;	 
			
			Если Ккк < МассивАргументов.Количество()-1 Тогда
				Команда = Команда + ",";
			КонецЕсли;	 
		КонецЦикла;
	КонецЕсли;	 
	
	Команда = Команда + ")";
	
	Отладка("Выполняю: " + Команда);
	Выполнить(Команда);
КонецПроцедуры

&НаКлиенте
Функция СформироватьОписаниеОшибки(Знач Стр,ИмяФайла,ИмяПроцедуры) Экспорт
	Стр = СтрЗаменить(Стр,Символы.ПС,"");
	Стр = СтрЗаменить(Стр,Символы.ВК,"");
	Стр = Стр + "; ИмяФайла="+ИмяФайла + ", ИмяПроцедуры="+ИмяПроцедуры;
	Возврат Стр;
КонецФункции

&НаКлиенте
Функция ПолучитьРезультатПрохожденияТестовСценария(ИДСтроки)
	ИД = МассивИДСтрокиДерева.Найти(ИДСтроки);
	Если ИД = Неопределено  Тогда
		Сообщить("Неизвестная ошибка в ПолучитьРезультатПрохожденияТестовСценария!");
		Возврат Неопределено;
	КонецЕсли;	 
	
	Возврат МассивРезультатПрохожденияТестовСценария[ИД]; 
КонецФункции

&НаСервереБезКонтекста
Процедура ОтменитьТранзакциюСервер()
	Пока ТранзакцияАктивна() Цикл
		ОтменитьТранзакцию();
	КонецЦикла;
КонецПроцедуры

&НаКлиенте
Процедура ДействияПослеЗавершенияСценария(СтрокаСценария,БылаОшибка = Ложь,ОписаниеОшибки = Неопределено)
	ВызватьМетодСценарияЕслиОнЕсть(СтрокаСценария, "ПередОкончаниемСценария",,БылаОшибка,ОписаниеОшибки);
КонецПроцедуры

&НаКлиенте
Функция ПроверитьНаличиеИнструментаДляСозданияСкриншотов()
	Если НЕ Объект.СоздаватьИнструкциюHTML и НЕ Объект.ДелатьСкриншотПриВозникновенииОшибки и НЕ Объект.СоздаватьИнструкциюMarkdown Тогда
		Возврат Истина;
	КонецЕсли;  
	
	Если Объект.СоздаватьИнструкциюHTML Тогда
		Если СокрЛП(Объект.КаталогOutputИнструкцияHTML) = "" Тогда
			Сообщить("КаталогOutputИнструкцияHTML не задан!");
			Возврат Ложь;
		КонецЕсли;  
	КонецЕсли;	 
	Если Объект.СоздаватьИнструкциюMarkdown Тогда
		Если СокрЛП(Объект.КаталогOutputИнструкцияMarkdown) = "" Тогда
			Сообщить("КаталогOutputИнструкцияMarkdown не задан!");
			Возврат Ложь;
		КонецЕсли;  
	КонецЕсли;	 
	Если Объект.ДелатьСкриншотПриВозникновенииОшибки Тогда
		Если СокрЛП(Объект.КаталогOutputСкриншоты) = "" Тогда
			Сообщить("КаталогOutputСкриншоты не задан!");
			Возврат Ложь;
		КонецЕсли;  
	КонецЕсли;	 
	Если ЭтоLinux Тогда 
		Возврат Истина;
	Иначе 
		ВременныйФайл = ПолучитьИмяВременногоФайла("png");
		СделатьСкриншот(ВременныйФайл);
		Если НЕ ФайлСуществуетКомандаСистемы(ВременныйФайл) Тогда
			Сообщить("НЕ найден инструмент по созданию скриншотов.");
			Возврат Ложь;
		КонецЕсли;	 
		
		Возврат Истина;
	КонецЕсли;
	
	//ИмяФайлаЛога = ПолучитьИмяВременногоФайла("txt");
	//Команда = "nircmd consolewrite test > " + ИмяФайлаЛога;
	////Команда = "nircmd > " + ИмяФайла;
	//КомандаСистемы(Команда);
	//
	//Текст = Новый ЧтениеТекста;
	//Текст.Открыть(ИмяФайлаЛога,"UTF-8");
	//
	//ИнструментУстановлен = Ложь;
	//Пока Истина Цикл
	//	Стр = Текст.ПрочитатьСтроку();
	//	Если Стр = Неопределено Тогда
	//		Прервать;
	//	КонецЕсли;	 
	//	
	//	ИнструментУстановлен = Истина;
	//	Сообщить(Стр);
	//КонецЦикла;	
	//
	//Текст.Закрыть();
	//
	//
	//Если НЕ ИнструментУстановлен Тогда
	//	Сообщить("Не могу создать инструкцию HTML, т.к. не установлен nircmd.");
	//КонецЕсли;  
	//
	//Возврат ИнструментУстановлен;
КонецФункции

&НаКлиенте
Процедура СделатьСкриншот(ИмяФайла) Экспорт
	//Команда = "nircmd savescreenshot " + ИмяФайла;
	//ЗапуститьПриложение(Команда);
	
	Команда = Объект.КомандаСделатьСкриншот + " """ + ИмяФайла + """";
	Если ЭтоLinux Тогда 
		//Команда = "import -window root " + ИмяФайла;
		КомандаСистемы(Команда);
	Иначе 
		//Команда = """C:\Program Files (x86)\IrfanView\i_view32.exe"" /capture=1 /convert=""" + ИмяФайла + """";
		Если ЕстьПоддержкаАсинхронныхВызовов Тогда
			ВыполнитьКомандуОСБезПоказаЧерногоОкна(Команда);
		Иначе	
			ЗапуститьПриложение(Команда,,Истина);
		КонецЕсли;	 
		
	КонецЕсли;
	
КонецПроцедуры

&НаКлиенте
Функция СоздатьИмяФайлаДляСкриншота(Каталог) Экспорт
	Возврат Каталог + "\ScreenShot_" + СтрЗаменить(ТекущаяУниверсальнаяДатаВМиллисекундах(),Символы.НПП,"") + ".png";
КонецФункции	

&НаКлиенте
Процедура ДобавитьВЛогИнструкцииHTMLВыполненияШага(СтруткураШага = Неопределено) Экспорт
	
	Если СкриншотСделанВСценарии Тогда
		Возврат;
	КонецЕсли;	 
	
	Если НЕ Объект.СоздаватьИнструкциюHTML Тогда
		Возврат;
	КонецЕсли;  
	
	Если СтруткураШага = Неопределено Тогда
		ТекИД_ВыполненногоШагаВМассиве = ТекИД_ШагаВМассиве;
		Шаги                           = МассивСценариевДляВыполнения[ТекИД_СценарияВМассиве].Шаги;
		СтруткураШага                  = Шаги[ТекИД_ШагаВМассиве];
	КонецЕсли;	 
	
	
	
	
	ИмяФайлаСкриншота = СоздатьИмяФайлаДляСкриншота(Объект.КаталогOutputИнструкцияHTML);
	СделатьСкриншот(ИмяФайлаСкриншота);
	
	ТД = Новый ТекстовыйДокумент();
	ТД.Прочитать(ИмяФайлаЛогаИнструкцииHTML,КодировкаТекста.UTF8);
	
	ТД.ДобавитьСтроку("НачалоШага");
	
	СтрокаШага = СтруткураШага.Имя;
	Если СтруткураШага.ШагСПараметрамиВТаблице = Истина Тогда
		Для каждого СтрПараметрыТаблицы Из СтруткураШага.ПараметрыТаблицы Цикл
			СтрокаШага = СтрокаШага + "\n" + СтрПараметрыТаблицы;
		КонецЦикла;
	КонецЕсли;	 
	
	ТД.ДобавитьСтроку("ИмяШага=" + СтрокаШага);
	ТД.ДобавитьСтроку("Скриншот=" + ИмяФайлаСкриншота);
	
	ТД.Записать(ИмяФайлаЛогаИнструкцииHTML,КодировкаТекста.UTF8);
КонецПроцедуры

&НаКлиенте
Процедура ДобавитьВЛогИнструкцииMarkdownВыполненияШага(СтруткураШага = Неопределено) Экспорт
	
	Если СкриншотСделанВСценарии Тогда
		Возврат;
	КонецЕсли;	 
	
	Если НЕ Объект.СоздаватьИнструкциюMarkdown Тогда
		Возврат;
	КонецЕсли;  
	
	Если СтруткураШага = Неопределено Тогда
		ТекИД_ВыполненногоШагаВМассиве = ТекИД_ШагаВМассиве;
		Шаги                           = МассивСценариевДляВыполнения[ТекИД_СценарияВМассиве].Шаги;
		СтруткураШага                  = Шаги[ТекИД_ШагаВМассиве];
	КонецЕсли;	 
	
	
	
	
	ИмяФайлаСкриншота = СоздатьИмяФайлаДляСкриншота(Объект.КаталогOutputИнструкцияMarkdown);
	СделатьСкриншот(ИмяФайлаСкриншота);
	
	ТД = Новый ТекстовыйДокумент();
	ТД.Прочитать(ИмяФайлаЛогаИнструкцииMarkdown,КодировкаТекста.UTF8);
	
	ТД.ДобавитьСтроку("НачалоШага");
	
	СтрокаШага = СтруткураШага.Имя;
	Если СтруткураШага.ШагСПараметрамиВТаблице = Истина Тогда
		Для каждого СтрПараметрыТаблицы Из СтруткураШага.ПараметрыТаблицы Цикл
			СтрокаШага = СтрокаШага + "\n" + СтрПараметрыТаблицы;
		КонецЦикла;
	КонецЕсли;	 
	
	ТД.ДобавитьСтроку("ИмяШага=" + СтрокаШага);
	ТД.ДобавитьСтроку("Скриншот=" + ИмяФайлаСкриншота);
	
	ТД.Записать(ИмяФайлаЛогаИнструкцииMarkdown,КодировкаТекста.UTF8);
КонецПроцедуры

&НаКлиенте
Функция ПолучитьЗначениеДляПередачиВМетод(Значение,Тип)
	Если Тип = "Строка" Тогда
		Возврат """" + СтрЗаменить(Значение,"""","""""") + """";
	ИначеЕсли Тип = "Число" Тогда
		Возврат Значение;
	ИначеЕсли Тип = "Дата" Тогда
		Возврат ПреобразоватьКДатеСтроку(Значение);
	Иначе
		ВызватьИсключение "Неизвестный Тип: " + Тип + " в ПолучитьЗначениеДляПередачиВМетод";
	КонецЕсли;	 
КонецФункции

&НаСервере
Функция ПолучитьЗначениеДляПередачиВМетодСервер(Значение,Тип)
	Если Тип = "Строка" Тогда
		Возврат """" + СтрЗаменить(Значение,"""","""""") + """";
	ИначеЕсли Тип = "Число" Тогда
		Возврат Значение;
	ИначеЕсли Тип = "Дата" Тогда
		Возврат ПреобразоватьКДатеСтрокуСервер(Значение);
	Иначе
		ВызватьИсключение "Неизвестный Тип: " + Тип + " в ПолучитьЗначениеДляПередачиВМетод";
	КонецЕсли;	 
КонецФункции

&НаСервере
Функция ПреобразоватьКДатеСтрокуСервер(Знач Стр) 
	НачСтр = Стр;
	//Зн = Дата(Стр);
	Год   = 0;
	Месяц = 0;
	День  = 0;
	
	Поз  = Найти(Стр,".");
	День = Число(Лев(Стр,Поз-1));
	Стр = Сред(Стр,Поз+1);
	
	Поз   = Найти(Стр,".");
	Месяц = Число(Лев(Стр,Поз-1));
	Стр   = Сред(Стр,Поз+1);
	
	Год   = Число(Стр);
	Если Год < 100 Тогда
		Год = Год + 2000;
	КонецЕсли;
	
	Зн = Дата(Год,Месяц,День);
	
	Зн = Формат(Зн,"ДФ=yyyyMMdd");
	Зн = "'" + Зн + "'";
	
	Возврат Зн;
КонецФункции


&НаКлиенте
Процедура ЗапомнитьСостоянияКонтекстовДоВыполненияШага(Контекст,КонтекстСохраняемый,ИдСтроки)
	СостоянияКонтекстовДоВыполненияШага = Новый Структура;
	СостоянияКонтекстовДоВыполненияШага.Вставить("Контекст",СкопироватьСтруктуру(Контекст));
	СостоянияКонтекстовДоВыполненияШага.Вставить("КонтекстСохраняемый",СкопироватьСтруктуру(КонтекстСохраняемый));
	СостоянияКонтекстовДоВыполненияШага.Вставить("ИдСтроки",ИдСтроки);
	
	Ном = -1;
	Для каждого Элем Из МассивСостоянияКонтекстовДоВыполненияШага Цикл
		Ном = Ном + 1;
		Если Элем.ИдСтроки = ИдСтроки Тогда
			МассивСостоянияКонтекстовДоВыполненияШага.Удалить(Ном);
			Прервать;
		КонецЕсли;	 
	КонецЦикла;
	
	МассивСостоянияКонтекстовДоВыполненияШага.Добавить(СостоянияКонтекстовДоВыполненияШага);
КонецПроцедуры

&НаКлиенте
Функция ПолучитьСостоянияКонтекстовПоИдСтроки(ИдСтроки)
	Для каждого Элем Из МассивСостоянияКонтекстовДоВыполненияШага Цикл
		Если Элем.ИдСтроки = ИдСтроки Тогда
			Возврат Элем;
		КонецЕсли;	 
	КонецЦикла;
	
	Возврат Неопределено;
КонецФункции	

&НаКлиенте
Процедура ВыполнитьШаг()
	Если ПрекратитьВыполнениШаговТакКакЗакончилсяСценарий Тогда
		Возврат;
	КонецЕсли; 
	
	ТекИД_ВыполненногоШагаВМассиве = ТекИД_ШагаВМассиве;
	
	Шаги = МассивСценариевДляВыполнения[ТекИД_СценарияВМассиве].Шаги;
	
	ТекШаг = Шаги[ТекИД_ШагаВМассиве];
	
	
	
	
	ИДСтрокиШага                       = ТекШаг.СтрокаШага;
	ИДСтрокиСценария                   = МассивСценариевДляВыполнения[ТекИД_СценарияВМассиве].СтрокаДерева;
	РезультатПрохожденияТестовСценария = ПолучитьРезультатПрохожденияТестовСценария(ИДСтрокиСценария);
	РезультатПрохожденияТестовШагов    = РезультатПрохожденияТестовСценария.РезультатПрохожденияТестовШагов;
	
	СтрокаШага     = МассивСтрокДереваДанныеФормы[ИДСтрокиШага];
	СтрокаСценария = МассивСтрокДереваДанныеФормы[ИДСтрокиСценария];
	
	
	
	//Элементы.ДеревоТестов.ТекущаяСтрока = СтрокаШага.ПолучитьИдентификатор();
	
	РезультатПрохожденияШага = Новый Структура;
	РезультатПрохожденияШага.Вставить("Имя",СтрокаШага.Имя);
	РезультатПрохожденияШага.Вставить("ВремяНачала",ТекущаяУниверсальнаяДатаВМиллисекундах());
	
	
	АдресСнипета = ТекШаг.АдресСнипета;
	Если СокрЛП(АдресСнипета) = "" Тогда
		СтрокаШага.Статус = "Pending";
		СтрокаШага.ТипКартинки = 6;
		СтрокаСценария.Статус         = СтрокаШага.Статус;
		ОписаниеОшибки = "Пустой адрес снипета у шага: " + ТекШаг.Имя;
		
		РезультатПрохожденияТестовСценария.Вставить("ВремяОкончания",ТекущаяУниверсальнаяДатаВМиллисекундах());
		РезультатПрохожденияТестовСценария.Вставить("ОписаниеОшибки",ОписаниеОшибки);
		РезультатПрохожденияШага.Вставить("ВремяОкончания",ТекущаяУниверсальнаяДатаВМиллисекундах());
		РезультатПрохожденияШага.Вставить("ОписаниеОшибки",ОписаниеОшибки);
		РезультатПрохожденияШага.Вставить("Статус",СтрокаШага.Статус);
		
		СделатьСообщение(ОписаниеОшибки);
		
		РезультатПрохожденияТестовШагов.Добавить(РезультатПрохожденияШага);
		
		БылаОшибка     = Ложь;
		ОписаниеОшибки = "";
		ДействияПослеЗавершенияСценария(СтрокаСценария,БылаОшибка,ОписаниеОшибки);
		Если БылаОшибка Тогда
			СтатусЗапускаСценариев = Ложь;		
			СтрокаСценария.Статус  = "Failed";
			РезультатПрохожденияТестовСценария.Вставить("ОписаниеОшибки",ОписаниеОшибки);
		КонецЕсли;
		
		
		ПрекратитьВыполнениШаговТакКакЗакончилсяСценарий = Истина;
		
		Если Объект.ДелатьСкриншотПриВозникновенииОшибки Тогда
			СделатьСкриншотВозникновенияОшибки(СтрокаШага,СтрокаСценария,РезультатПрохожденияТестовСценария);
		Иначе	
			//выполняем следующий сценарий
			ПерейтиКВыполнениюСледующегоСценария();
		КонецЕсли;	 
		
		
		Возврат;
	КонецЕсли;	 
	
	
	//ТаблицаКонтекстовОбработок
	ИД = МассивИменКонтекстовОбработок.Найти(АдресСнипета);
	ОбработкаТеста = ТаблицаКонтекстовОбработок[ИД].Обработка;
	КонтекстОтладки = ТаблицаОбработокДляОтладки.Получить(ТекШаг.СтрокаРеальнойПроцедуры);
	Если КонтекстОтладки <> Неопределено Тогда 
		ОбработкаТеста = КонтекстОтладки.Обработка;
	КонецЕсли;
	
	ИмяПроцедуры     = ТекШаг.СтрокаРеальнойПроцедуры;
	СписокАргументов = ТекШаг.ЗначенияПараметров;
	
	
	МассивПараметров = ПолучитьМассивПараметровИзСписокАргументов(СписокАргументов);
	
	Если СтрокаШага.ШагСПараметрамиВТаблице = Истина Тогда
		ПарамТаблица = Новый Массив;
		
		ПодчиненныеСтроки = СтрокаШага.ПолучитьЭлементы();
		Для каждого СтрокиТаблицы Из ПодчиненныеСтроки Цикл
			СтрокаПарамТаблица = Новый Структура;
			
			НомерКолонки = 0;
			Для каждого Колонка Из СтрокиТаблицы.ПараметрыТаблицы Цикл
				НомерКолонки       = НомерКолонки + 1;
				СтруктураПараметра = Колонка.Значение;
				Значение           = ПолучитьЗначениеДляПередачиВМетод(СтруктураПараметра.Значение,СтруктураПараметра.Тип);
				Значение           = Вычислить(Значение);
			
				СтрокаПарамТаблица.Вставить("Кол" + НомерКолонки,Значение);
			КонецЦикла;
			
			ПарамТаблица.Добавить(СтрокаПарамТаблица);
		КонецЦикла;
		МассивПараметров.Добавить(ПарамТаблица);
	КонецЕсли;	 
	
	СтрОшибка       = Неопределено;
	ШагВыполнен     = Ложь;
	ШагНеРеализован = Ложь;
	Попытка
		
		Если Объект.РежимВыполненияСценарияСВыбранногоШага = Истина Тогда
			СохраненнаяСтруктура = ПолучитьСостоянияКонтекстовПоИдСтроки(СтрокаШага.ИдСтроки);
			Если СтрокаШага.ВыполнятьСценарийСЭтогоШага = Истина Тогда 
				Если СохраненнаяСтруктура <> Неопределено Тогда
					ОбъектКонтекст            = СкопироватьСтруктуру(СохраненнаяСтруктура.Контекст);
					ОбъектКонтекстСохраняемый = СкопироватьСтруктуру(СохраненнаяСтруктура.КонтекстСохраняемый);
				Иначе	
					ЗапомнитьСостоянияКонтекстовДоВыполненияШага(ОбъектКонтекст,ОбъектКонтекстСохраняемый,СтрокаШага.ИдСтроки);
				КонецЕсли;	 
			Иначе	
				//значит в этот раз запустить с этого шага не получится, надо запомнить контекст для последующих запусков
				ЗапомнитьСостоянияКонтекстовДоВыполненияШага(ОбъектКонтекст,ОбъектКонтекстСохраняемый,СтрокаШага.ИдСтроки);
			КонецЕсли;	 
		ИначеЕсли Объект.СохранятьКонтекстыПередВыполнениемШагов Тогда
			ЗапомнитьСостоянияКонтекстовДоВыполненияШага(ОбъектКонтекст,ОбъектКонтекстСохраняемый,СтрокаШага.ИдСтроки);
		КонецЕсли;	 
		
		
		ОбработкаТеста.Контекст            = ОбъектКонтекст;
		ОбработкаТеста.КонтекстСохраняемый = ОбъектКонтекстСохраняемый;
		
		Если Объект.ДелатьЛогВыполненияСценариевВЖР Тогда
			ЗаписатьЛогВЖРПередВыполнениемШага(ТекШаг.Имя);
		КонецЕсли;	 
		
		
		СкриншотСделанВСценарии = Ложь;
		
		ВсёЕщёИдётВыполнениеШагов = ВсёЕщёИдётВыполнениеШагов + 1;
		ВызватьМетод(ОбработкаТеста, ИмяПроцедуры, МассивПараметров);
		ВсёЕщёИдётВыполнениеШагов = ВсёЕщёИдётВыполнениеШагов - 1;
		
		ОбъектКонтекст            = ОбработкаТеста.Контекст;
		ОбъектКонтекстСохраняемый = ОбработкаТеста.КонтекстСохраняемый;
		
		ШагВыполнен = Истина;
		
		Если НЕ ТекШаг.ЭтоШагКонтекста Тогда
			ДобавитьВЛогИнструкцииHTMLВыполненияШага(ТекШаг);
			ДобавитьВЛогИнструкцииMarkdownВыполненияШага(ТекШаг);
			Если Не ЭтоПрерывающйВидеоШаг(ТекШаг) Тогда
				КоличествоШаговВДаннойЧастиВидео = КоличествоШаговВДаннойЧастиВидео + 1;
			КонецЕсли;	 
		КонецЕсли;	 
		
	Исключение
		
		Отладка("ОписаниеОшибки()="+ОписаниеОшибки());
		ОписаниеОшибкиСтр = ОписаниеОшибки();
		Если Найти(ОписаниеОшибкиСтр,"}: Не реализовано.") > 0 Тогда //тогда это Pending
			СделатьСообщение("Шаг (" + ТекШаг.Имя + ") не реализован.");
			СтрОшибка = "Не реализовано.";
			ШагНеРеализован = Истина;
		Иначе
			//значит возникла ошибка
			СделатьСообщение("Шаг (" + ТекШаг.Имя + ") не выполнен.");
			СтрОшибка = СформироватьОписаниеОшибки(ОписаниеОшибки(),АдресСнипета,ИмяПроцедуры);
			СделатьСообщение(СтрОшибка);
		КонецЕсли;
	КонецПопытки;
	
	
	
	//ПромСтрока = Неопределено;
	//НайтиСтрокуДереваПоИдСтроки(СтрокаШага.ИдСтроки,Объект.ДеревоТестов.ПолучитьЭлементы(),ПромСтрока);
	//СтрокаШага = ПромСтрока;
	
	РезультатПрохожденияШага.Вставить("ВремяОкончания",ТекущаяУниверсальнаяДатаВМиллисекундах());
	Если ШагВыполнен Тогда
		СтрокаШага.Статус = "Success";
		СтрокаШага.ТипКартинки = 4;
		РезультатПрохожденияТестовШагов.Добавить(РезультатПрохожденияШага);
		РезультатПрохожденияШага.Вставить("Статус",СтрокаШага.Статус);
		
		
		
		
		ПерейтиКВыполнениюСледующегоШага();
	Иначе	
		ЗапомнитьСтрокиДереваДанныеФормы();
		СтрокаШага     = МассивСтрокДереваДанныеФормы[ИДСтрокиШага];
		СтрокаСценария = МассивСтрокДереваДанныеФормы[ИДСтрокиСценария];
		
		Если ШагНеРеализован Тогда
			СтрокаШага.Статус = "Pending";
			СтрокаШага.ТипКартинки = 6;
		Иначе
			СтатусЗапускаСценариев = Ложь;		
			СтрокаШага.Статус      = "Failed";
			СтрокаШага.ТипКартинки = 5;
		КонецЕсли; 
		РезультатПрохожденияШага.Вставить("ОписаниеОшибки",СтрОшибка);
		РезультатПрохожденияШага.Вставить("Статус",СтрокаШага.Статус);
		РезультатПрохожденияТестовСценария.Вставить("ВремяОкончания",ТекущаяУниверсальнаяДатаВМиллисекундах());
		РезультатПрохожденияТестовСценария.Вставить("ОписаниеОшибки",СтрОшибка);
		
		СтрокаСценария.Статус         = СтрокаШага.Статус;
		
		БылаОшибка     = Ложь;
		ОписаниеОшибки = "";
		ДействияПослеЗавершенияСценария(СтрокаСценария,БылаОшибка,ОписаниеОшибки);
		РезультатПрохожденияТестовШагов.Добавить(РезультатПрохожденияШага);

		Если БылаОшибка Тогда
			СтатусЗапускаСценариев = Ложь;		
			СтрокаСценария.Статус  = "Failed";
			РезультатПрохожденияТестовСценария.Вставить("ОписаниеОшибки",ОписаниеОшибки);
		КонецЕсли;
		
		ДобавитьШагиВРезультатПрохожденияТестовШаговКоторыеНеВыполнялись(Шаги,ТекИД_ШагаВМассиве,РезультатПрохожденияТестовШагов);
		ПрекратитьВыполнениШаговТакКакЗакончилсяСценарий = Истина;
		
		Если СтрокаСценария.Статус = "Failed" и Объект.ДелатьСкриншотПриВозникновенииОшибки Тогда
			СделатьСкриншотВозникновенияОшибки(СтрокаШага,СтрокаСценария,РезультатПрохожденияТестовСценария);
		Иначе	
			ПерейтиКВыполнениюСледующегоСценария();
		КонецЕсли;	 
		
		
	КонецЕсли;
	
КонецПроцедуры


&НаКлиенте
Процедура ЗапретитьВыполнениеШагов() Экспорт
	Объект.ОстановитьВыполнениеШагов = Истина;
КонецПроцедуры

&НаКлиенте
Процедура УстановитьТекущемуШагуФлагЧтоОнДолженСчитатьсяУпавшим()
	Если ТекИД_ШагаВМассиве = Неопределено Тогда
		Возврат;
	КонецЕсли; 
	
	Если (МассивСценариевДляВыполнения.Количество()-1) < ТекИД_СценарияВМассиве Тогда
		Возврат;
	КонецЕсли;	 
	
	
	Если ТекИД_ШагаВМассиве >= 0 Тогда
		Шаги   = МассивСценариевДляВыполнения[ТекИД_СценарияВМассиве].Шаги;
		ТекШаг = Шаги[ТекИД_ШагаВМассиве];
		ТекШаг.Вставить("ШагСчитаетсяУпавшим",Истина);
	КонецЕсли;	 
КонецПроцедуры

&НаКлиенте
Процедура ПродолжитьВыполнениеШагов(ШагУпал = Ложь) Экспорт
	Объект.ОстановитьВыполнениеШагов = Ложь;
	
	Если ШагУпал Тогда
		УстановитьТекущемуШагуФлагЧтоОнДолженСчитатьсяУпавшим();
	КонецЕсли;	 
	
	Если ВсёЕщёИдётВыполнениеШагов  > 0 Тогда
		Возврат;
	КонецЕсли;	 
	
	Если МассивСценариевДляВыполнения <> Неопределено Тогда
		Если (МассивСценариевДляВыполнения.Количество()-1) < ТекИД_СценарияВМассиве Тогда
			Возврат;
		КонецЕсли;	
	КонецЕсли; 
	
	
	ПерейтиКВыполнениюСледующегоШага(Истина);
КонецПроцедуры

&НаСервереБезКонтекста
Функция ТранзакцияАктивнаСервер()
	Возврат ТранзакцияАктивна();
КонецФункции	




//работа с видео - начало
&НаКлиенте
Функция ПолучитьКомандуСкриптаСделатьФайлыTTS(ФайлПараметров)
	ИмяВременногоBAT = ПолучитьИмяВременногоФайла("bat");
	
	ИмяВременнойФичи = ПолучитьИмяВременногоФайла("feature");
	КопироватьФайлКомандаСистемы(Объект.КаталогФич,ИмяВременнойФичи);
	
	Стр = "oscript " + Объект.КаталогСкриптовСборкиВидео + "\MakeTTS.os " + ФайлПараметров + " """ + ИмяВременнойФичи + """";
	
	ЗТ = Новый ЗаписьТекста(ИмяВременногоBAT,КодировкаТекста.ANSI,,Истина); 
	ЗТ.ЗаписатьСтроку("chcp 65001");
	ЗТ.ЗаписатьСтроку(Стр); 
	ЗТ.Закрыть();
	
	//УдалитьФайлыКомандаСистемы(ИмяВременнойФичи);
	
	Возврат ИмяВременногоBAT;
КонецФункции	

&НаКлиенте
Процедура СоздатьФайлыTTS(ФайлПараметров)
	ПутьККоманде = ПолучитьКомандуСкриптаСделатьФайлыTTS(ФайлПараметров);
	КодВозврата  = ВыполнитьСкриптСделатьФайлыTTS(ПутьККоманде,"ЗакончитьЗаписьВидео");
	Если КодВозврата <> 0 Тогда
		Стр = "Ошибка при выполнении скрипта <" + ПутьККоманде + ">! КодВозврата = " + КодВозврата;
		СделатьСообщение(Стр);
		ВызватьИсключение Стр;
	КонецЕсли;	 
КонецПроцедуры

&НаКлиенте
Функция ВыполнитьСкриптСделатьФайлыTTS(ПутьККоманде,ИмяСкрипта)
	ВременныйФайл = ПолучитьИмяВременногоФайла("txt");
	
	Команда = ПутьККоманде + " > " + ВременныйФайл + " 2>&1";
	
	КодВозврата = ВыполнитьКомандуОСБезПоказаЧерногоОкна(Команда);
	Если КодВозврата <> 0 Тогда
		СделатьСообщение("Скрипт " + ИмяСкрипта + " не выполнен! КодВозврата="+КодВозврата);
		БылаОшибкаСкриптовСборкиВидео = Истина;
	КонецЕсли;	 
	Возврат КодВозврата;
КонецФункции	

&НаКлиенте
Функция ЗагрузитьФайлВМассив(ИмяФайла)
	Массив = Новый Массив;
	
	Текст = Новый ЧтениеТекста;
	Текст.Открыть(ИмяФайла,"UTF-8");
	
	Пока Истина Цикл
		Стр = Текст.ПрочитатьСтроку();
		Если Стр = Неопределено Тогда
			Прервать;
		КонецЕсли;	 
		
		Массив.Добавить(Стр);
	КонецЦикла;	
	
	Текст.Закрыть();
	
	Возврат Массив;
КонецФункции	

&НаКлиенте
Функция ПолучитьМассивTTS(Каталог)
	МассивСписокШагов  = ЗагрузитьФайлВМассив(Каталог + "\list.txt");
	МассивДлительность = ЗагрузитьФайлВМассив(Каталог + "\duration.txt");
	
	Если МассивСписокШагов.Количество() <> МассивДлительность.Количество() Тогда
		ВызватьИсключение "Не смог прочитать данные по TTS из служебных файлов!";
	КонецЕсли;	 
	
	Массив = Новый Массив;
	
	Для Ккк = 0 По МассивСписокШагов.Количество()-1 Цикл
		Шаг = МассивСписокШагов[Ккк];
		Длительность = Число(МассивДлительность[Ккк]);
		
		Массив.Добавить(Новый Структура("Шаг,Длительность,ИмяФайла",Шаг,Длительность,Каталог + "\" + XmlСтрока(Ккк+1) + ".mp3"));
	КонецЦикла;
	
	Возврат Массив;
КонецФункции	

&НаКлиенте
Процедура ВыполнитьПодготовкуКЗаписиВидео()
	ФайлПараметров = Объект.КаталогСкриптовСборкиВидео + "\StartVideo.json";
	ПараметрыФайла = ПрочитатьСтруктуруИзJSONФайлаКлиент(ФайлПараметров);
	DoTTS  = ПараметрыФайла["DoTTS"];	
	Если DoTTS = "true" Тогда
		СоздатьФайлыTTS(ФайлПараметров);
	КонецЕсли;	 
	
	КаталогДляФайловTTS = ПараметрыФайла["КаталогДляФайловTTS"];
	КаталогДляФайловTTS = СтрЗаменить(КаталогДляФайловTTS,"/","\");
	
	МассивTTS           = ПолучитьМассивTTS(КаталогДляФайловTTS);
КонецПроцедуры

&НаКлиенте
Процедура ПреобразоватьСубтитрыВФорматSRT(ЛогФайл,ФайлSRT,ФайлTTS)
	ФайлSRT = СтрЗаменить(ФайлSRT,"\\","\");
	
	Если ФайлСуществуетКомандаСистемы(ФайлSRT) Тогда
		УдалитьФайлыКомандаСистемы(ФайлSRT);
	КонецЕсли;	 
	
	Если ФайлСуществуетКомандаСистемы(ФайлTTS) Тогда
		УдалитьФайлыКомандаСистемы(ФайлTTS);
	КонецЕсли;	 
	
	
	МассивСубтитров = Новый Массив();
	
	Текст = Новый ЧтениеТекста;
	Текст.Открыть(ЛогФайл,"UTF-8");
	
	Пока Истина Цикл
		Стр = Текст.ПрочитатьСтроку();
		Если Стр = Неопределено Тогда
			Прервать;
		КонецЕсли;	 
		
		Массив = РазложитьСтрокуВМассивПодстрок(Стр,"|||");
		
		ЗначениеМассива = Новый Структура;
		ЗначениеМассива.Вставить("Время",Число(Массив[0]));
		ЗначениеМассива.Вставить("ИмяШага",Массив[1]);
		
		МассивСубтитров.Добавить(ЗначениеМассива);
	КонецЦикла;	
	
	Текст.Закрыть();
	
	
	Если МассивСубтитров.Количество() = 0 Тогда
		ЗТ = Новый ЗаписьТекста(ФайлSRT,"UTF-8",,Истина); 
		ЗТ.ЗаписатьСтроку(""); 
		ЗТ.Закрыть();
		ЗТ = Новый ЗаписьТекста(ФайлTTS,"UTF-8",,Истина); 
		ЗТ.ЗаписатьСтроку(""); 
		ЗТ.Закрыть();
		Возврат;
	КонецЕсли;	
	
	ЗТ = Новый ЗаписьТекста(ФайлSRT,"UTF-8",,Истина); 
	НачальноеВремя = МассивСубтитров[0].Время;
	
	Ном = 0;
	Для Ккк = 0 По МассивСубтитров.Количество()-1 Цикл
		Ном = Ном + 1;
		ЗТ.ЗаписатьСтроку(СтрЗаменить("" + Ном,Символы.НПП,"")); 
		ТекущаяВременнаяОтметка   = МассивСубтитров[Ккк].Время;
		СледующаяВременнаяОтметка = Неопределено;
		Если Ккк < (МассивСубтитров.Количество()-1) Тогда
			СледующаяВременнаяОтметка   = МассивСубтитров[Ккк+1].Время;
		КонецЕсли;	 
		
		
		СтрокаДлительностиТитра = ПолучитьСтркуДлительностиТитра(НачальноеВремя,ТекущаяВременнаяОтметка,СледующаяВременнаяОтметка,МассивСубтитров[Ккк].ИмяШага,ФайлTTS);
		ЗТ.ЗаписатьСтроку(СтрокаДлительностиТитра);
		
		
		
		ИмяШага = МассивСубтитров[Ккк].ИмяШага;
		//Пока Найти(ИмяШага,"  ") > 0 Цикл
			МассивСтрок = РазложитьСтрокуВМассивПодстрок(ИмяШага,"\n");
			Для каждого Стр Из МассивСтрок Цикл
				СтрокаДляЗаписи = Стр;
				Если Лев(СокрЛП(СтрокаДляЗаписи),1) <> "|" Тогда
					Пока Найти(СтрокаДляЗаписи,"  ") > 0 Цикл
						СтрокаДляЗаписи = СтрЗаменить(СтрокаДляЗаписи,"  "," ");
					КонецЦикла;
				КонецЕсли;	 
				ЗТ.ЗаписатьСтроку(СтрокаДляЗаписи); 
			КонецЦикла;
			
		//КонецЦикла; 
		
		
		ЗТ.ЗаписатьСтроку(""); 
	КонецЦикла;
	
	ЗТ.Закрыть();
	
	Отладка("Записан файл субтитров " + ФайлSRT);
КонецПроцедуры

&НаКлиенте
Функция ФорматSRT(КолМС)
	Сек = Цел(КолМС / 1000);
	МС  = КолМС - Сек*1000; 
	
	Дат = '00010101';
	Дат = Дат + Сек;
	Время = Формат(Дат,"ДЛФ=T");
	Если Время = "" Тогда
		Время = "00:00:00";
	КонецЕсли;	 
	Если Сред(Время,2,1) = ":" Тогда
		Время = "0" + Время;
	КонецЕсли;	 
	
	
	МС = Строка(МС);
	Пока СтрДлина(МС) < 3 Цикл
		МС = МС + "0";
	КонецЦикла; 
	
	Стр = Время + "," + МС;
	
	Возврат Стр;
КонецФункции	

&НаКлиенте
Функция ПолучитьСтркуДлительностиТитра(Знач НачальноеВремя,Знач ТекущаяВременнаяОтметка,Знач СледующаяВременнаяОтметка,ИмяШага,ФайлTTS)
	ДержатьТитрМС = 2000;
	
	
	Если СледующаяВременнаяОтметка = Неопределено Тогда
		СледующаяВременнаяОтметка = ТекущаяВременнаяОтметка + 3000;
	КонецЕсли;	 
	
	ПрошлоКоличествоМилиСекундСлед = СледующаяВременнаяОтметка - НачальноеВремя;
	ДлительностьШагаРеальная = СледующаяВременнаяОтметка - ТекущаяВременнаяОтметка;
	
	
	ДлительностьТитра = Мин(ДлительностьШагаРеальная,3000);
	
	Люфт = 1000;
	
	ВремяНачало    = ТекущаяВременнаяОтметка - НачальноеВремя + Люфт;
	Если ВремяНачало < 0 Тогда
		ВремяНачало = 0;
	КонецЕсли;	 
	
	
	ЗначенияTTS = ПолучитьЗначенияTTSШага(СокрЛП(ИмяШага));
	Если ЗначенияTTS <> Неопределено Тогда
		ЗТ = Новый ЗаписьТекста(ФайлTTS,"UTF-8",,Истина); 
		ЗТ.ЗаписатьСтроку("Время="+XmlСтрока(ВремяНачало) + "|" + ЗначенияTTS.ИмяФайла); 
		
		ЗТ.Закрыть();
		
		
		
		Если ДлительностьТитра < ЗначенияTTS.Длительность*1000 Тогда
			ДлительностьТитра = ЗначенияTTS.Длительность*1000;
		КонецЕсли;	 
	КонецЕсли;	 
	
	ВремяОкончание = ВремяНачало + ДлительностьТитра;
	
	Возврат "" + ФорматSRT(ВремяНачало) + " --> " + ФорматSRT(ВремяОкончание);
КонецФункции	

&НаКлиенте
Процедура ЗакончитьЗаписьВидеоОдногоСценария(НадоПрерватьСценарийДляВставки = Ложь,ШагВставки = Неопределено)
	Если НЕ Объект.ИдетЗаписьВидео Тогда
		Возврат;
	КонецЕсли;	 
	
	
	
	Объект.ИдетЗаписьВидео = Ложь;
	
	ФайлПараметров = "";
	ВыполнитьКомандуСкриптЗакончитьЗаписьВидео(ФайлПараметров);
	ПараметрыФайла = ПрочитатьСтруктуруИзJSONФайлаКлиент(ФайлПараметров);
	ФайлРезультат  = ПараметрыФайла["dst"];
	ФайлРезультат  = СтрЗаменить(ФайлРезультат,"/","\");
	
	Если Не ФайлСуществуетКомандаСистемы(ФайлРезультат) Тогда
		СделатьСообщение("Файл с записью видео <" + ФайлРезультат + "> не найден!");
		Возврат;
	КонецЕсли;	 
	
	//Отладка("Файл с записью видео <" + ФайлРезультат + "> найден!");
	
	ПреобразоватьСубтитрыВФорматSRT(ИмяФайлаСубтитров,ПараметрыФайла["subsfile"],ПараметрыФайла["ttsfile"]);
	
	ВыполнитьКомандуОбработатьСценарийВидео(ТекИД_СценарияВМассиве,НадоПрерватьСценарийДляВставки,ШагВставки);
	
	
КонецПроцедуры

&НаКлиенте
Функция ВыполнитьСкриптСборкиВидеоБезПоказаОкна(ПутьККоманде,ИмяСкрипта)
	ВременныйФайл = ПолучитьИмяВременногоФайла("txt");
	//ВременныйФайл = "c:\temp\" + СтрЗаменить(СтрЗаменить(ТекущаяДата(),":","")," ","_") + ".txt";
	
	Команда = ПутьККоманде + " > " + ВременныйФайл + " 2>&1";
	
	КодВозврата = ВыполнитьКомандуОСБезПоказаЧерногоОкна(Команда);
	Если КодВозврата <> 0 Тогда
		СделатьСообщение("Скрипт " + ИмяСкрипта + " не выполнен! КодВозврата="+КодВозврата);
		Сообщить("ФайлЛога=" + ВременныйФайл);
		БылаОшибкаСкриптовСборкиВидео = Истина;
	КонецЕсли;	 
	Возврат КодВозврата;
	//КомандаСистемы(Команда);
КонецФункции	

&НаКлиенте
Функция СоздатьФайлПараметровПоФиче(ФайлФичи)
	ВременныйФайл = ПолучитьИмяВременногоФайла("json");
	ЗТ = Новый ЗаписьТекста(ВременныйФайл,"UTF-8",,Истина); 
	ЗТ.ЗаписатьСтроку("{"); 
	ЗТ.ЗаписатьСтроку("""ФайлФичи"":""" + СтрЗаменить(ФайлФичи,"\","/") + ""","); 
	ЗТ.ЗаписатьСтроку("""КоличествоСценариев"":""" + СтрЗаменить(МассивСценариевДляВыполнения.Количество(),Символы.НПП,"") + ""","); 
	
	КолШагов = 0;
	Для каждого Элем Из МассивСценариевДляВыполнения Цикл
		Для каждого Шаг Из Элем.Шаги Цикл
			Если Шаг.ЭтоШагКонтекста Тогда
				Продолжить;
			КонецЕсли;	 
			КолШагов = КолШагов + 1;
		КонецЦикла;
	КонецЦикла;
	
	ЗТ.ЗаписатьСтроку("""КоличествоШагов"":""" + СтрЗаменить(КолШагов,Символы.НПП,"") + ""","); 
	ЗТ.ЗаписатьСтроку("""ВерсияVB"":""" + ПолучитьВерсиюОбработкиСервер(Истина) + ""","); 
	ЗТ.ЗаписатьСтроку("""КаталогOutputИнструкцияВидео"":""" + СтрЗаменить(Объект.КаталогOutputИнструкцияВидео,"\","/") + ""","); 
	
	ЗТ.ЗаписатьСтроку("""ПустоеЗначение"":""ПустоеЗначение"""); 
	ЗТ.ЗаписатьСтроку("}"); 
	ЗТ.Закрыть();
	                      
	Возврат ВременныйФайл;
КонецФункции	

&НаКлиенте
Процедура СделатьОдинФайлВидеоПоЗаписаннымДанным()
	Если НЕ Объект.СоздаватьИнструкциюВидео Тогда
		Возврат;
	КонецЕсли;	 
	
	Если БылаОшибкаСкриптовСборкиВидео Тогда
		Возврат;
	КонецЕсли;	 
	
	Если Не ЗначениеЗаполнено(Объект.КаталогСкриптовСборкиВидео) Тогда
		Возврат;
	КонецЕсли;	 
	
	
	ФайлПараметровФичи = СоздатьФайлПараметровПоФиче(Объект.КаталогФич);
	ПутьККоманде = ПолучитьКомандуСделатьОдинВидеоФайл(ФайлПараметровФичи);
	
	
	
	КодВозврата = ВыполнитьСкриптСборкиВидеоБезПоказаОкна(ПутьККоманде,"СделатьОдинФайлВидеоПоЗаписаннымДанным");
	Если КодВозврата <> 0 Тогда
		СделатьСообщение("Ошибка при выполнении скрипта <" + ПутьККоманде + ">! КодВозврата = " + КодВозврата);
		Возврат;
	КонецЕсли;	 
	
КонецПроцедуры

&НаКлиенте
Функция ПолучитьКомандуСделатьОдинВидеоФайл(ФайлПараметровФичи)
	
	
	ИмяВременногоBAT = ПолучитьИмяВременногоФайла("bat");
	ФайлПараметров = Объект.КаталогСкриптовСборкиВидео + "\StartVideo.json";
	Стр = "oscript " + Объект.КаталогСкриптовСборкиВидео + "\Finalize.os " + ФайлПараметров + " " + ФайлПараметровФичи;
	
	ЗТ = Новый ЗаписьТекста(ИмяВременногоBAT,КодировкаТекста.ANSI,,Истина); 
	ЗТ.ЗаписатьСтроку("chcp 65001");
	ЗТ.ЗаписатьСтроку(Стр); 
	ЗТ.Закрыть();
	
	
	Возврат ИмяВременногоBAT;
КонецФункции	

&НаКлиенте
Функция ПолучитьКомандуСкриптаЗаписьВидео()
	
	ИмяВременногоBAT = ПолучитьИмяВременногоФайла("bat");
	ФайлПараметров = Объект.КаталогСкриптовСборкиВидео + "\StartVideo.json";
	
	ПараметрыФайла = ПрочитатьСтруктуруИзJSONФайлаКлиент(ФайлПараметров);
	ФайлРезультат  = ПараметрыФайла["dst"];
	ФайлРезультат  = СтрЗаменить(ФайлРезультат,"\\","\");
	Если ФайлСуществуетКомандаСистемы(ФайлРезультат) Тогда
		УдалитьФайлыКомандаСистемы(ФайлРезультат);
	КонецЕсли;	 
	//Сообщить("dst=" + ПараметрыФайла["dst"]);
	
	
		
	
	Стр = "oscript " + Объект.КаталогСкриптовСборкиВидео + "\StartVideoRec.os " + ФайлПараметров;
	
	ЗТ = Новый ЗаписьТекста(ИмяВременногоBAT,КодировкаТекста.ANSI,,Истина); 
	ЗТ.ЗаписатьСтроку("chcp 65001");
	ЗТ.ЗаписатьСтроку(Стр); 
	ЗТ.Закрыть();
	
	
	Возврат ИмяВременногоBAT;
КонецФункции	

&НаКлиенте
Функция ПолучитьКомандуСкриптаЗакончитьЗаписьВидео(ФайлПараметров)
	ИмяВременногоBAT = ПолучитьИмяВременногоФайла("bat");
	ФайлПараметров = Объект.КаталогСкриптовСборкиВидео + "\StartVideo.json";
	
	Стр = "oscript " + Объект.КаталогСкриптовСборкиВидео + "\StopVideoRec.os " + ФайлПараметров;
	
	ЗТ = Новый ЗаписьТекста(ИмяВременногоBAT,КодировкаТекста.ANSI,,Истина); 
	ЗТ.ЗаписатьСтроку("chcp 65001");
	ЗТ.ЗаписатьСтроку(Стр); 
	ЗТ.Закрыть();
	
	
	Возврат ИмяВременногоBAT;
КонецФункции	

&НаКлиенте
Процедура ВыполнитьКомандуСкриптНачатьЗаписьВидео()
	Если БылаОшибкаСкриптовСборкиВидео Тогда
		Возврат;
	КонецЕсли;	 
	
	Если НЕ ЗначениеЗаполнено(Объект.КаталогСкриптовСборкиВидео) Тогда
		Возврат;
	КонецЕсли;	 
	
	ПутьККоманде = ПолучитьКомандуСкриптаЗаписьВидео();
	КодВозврата = ВыполнитьСкриптСборкиВидеоБезПоказаОкна(ПутьККоманде,"НачатьЗаписьВидео");
	Если КодВозврата <> 0 Тогда
		СделатьСообщение("Ошибка при выполнении скрипта <" + ПутьККоманде + ">! КодВозврата = " + КодВозврата);
		Возврат;
	КонецЕсли;	 
КонецПроцедуры

&НаКлиенте
Функция СоздатьФайлПараметровПоСценарию(ТекСценарий,ИД_СценарияВМассиве,НадоПрерватьСценарийДляВставки)
	ВременныйФайл = ПолучитьИмяВременногоФайла("json");
	ЗТ = Новый ЗаписьТекста(ВременныйФайл,"UTF-8",,Истина); 
	ЗТ.ЗаписатьСтроку("{"); 
	ЗТ.ЗаписатьСтроку("""ИмяСценария"":""" + ТекСценарий.Имя + ""","); 
	ЗТ.ЗаписатьСтроку("""ид"":""" + СтрЗаменить(ИД_СценарияВМассиве,Символы.НПП,"") + ""","); 
	Если НадоПрерватьСценарийДляВставки Тогда
		ЗТ.ЗаписатьСтроку("""НадоПрерватьСценарийДляВставки"":""" + "истина" + ""","); 
	Иначе	
		ЗТ.ЗаписатьСтроку("""НадоПрерватьСценарийДляВставки"":""" + "ложь" + ""","); 
	КонецЕсли;	 
	ЗТ.ЗаписатьСтроку("""КоличествоШаговВДаннойЧастиВидео"":""" + СтрЗаменить(КоличествоШаговВДаннойЧастиВидео,Символы.НПП,"") + ""","); 
	ЗТ.ЗаписатьСтроку("""ИДВставкиВВидео"":""" + СтрЗаменить(ИДВставкиВВидео,Символы.НПП,"") + ""","); 
	ЗТ.ЗаписатьСтроку("""ИмяЧастиВидео"":""---"","); 
	ЗТ.ЗаписатьСтроку("""ИмяЧастиСубтитры"":""---"","); 
	ЗТ.ЗаписатьСтроку("""ИмяЧастиTTS"":""---"","); 
	
	
	Если НЕ НадоПрерватьСценарийДляВставки Тогда
		//тогда надо передать все накопленные части
		ЗТ.ЗаписатьСтроку("""ИменаФайловЧастейВидео"":["); 
		Ид = 0;
		Для каждого ЧастьВидео Из МассивЧастейВидео Цикл
			Ид = Ид + 1;
			Стр = ЧастьВидео.ИмяЧастиВидео;
			//Стр = СтрЗаменить(Стр,"\","/");
			Если Ид = МассивЧастейВидео.Количество() Тогда
				ЗТ.ЗаписатьСтроку("""" + Стр + """"); 
			Иначе	
				ЗТ.ЗаписатьСтроку("""" + Стр + ""","); 
			КонецЕсли;	 
		КонецЦикла;
		ЗТ.ЗаписатьСтроку("],"); 
		
		
		ЗТ.ЗаписатьСтроку("""ИменаФайловСубтитров"":["); 
		Ид = 0;
		Для каждого ЧастьВидео Из МассивЧастейВидео Цикл
			Ид = Ид + 1;
			Стр = ЧастьВидео.ИмяЧастиСубтитры;
			//Стр = СтрЗаменить(Стр,"\","/");
			Если Ид = МассивЧастейВидео.Количество() Тогда
				ЗТ.ЗаписатьСтроку("""" + Стр + """"); 
			Иначе	
				ЗТ.ЗаписатьСтроку("""" + Стр + ""","); 
			КонецЕсли;	 
		КонецЦикла;
		ЗТ.ЗаписатьСтроку("],"); 
		
		
		ЗТ.ЗаписатьСтроку("""ИменаФайловTTS"":["); 
		Ид = 0;
		Для каждого ЧастьВидео Из МассивЧастейВидео Цикл
			Ид = Ид + 1;
			Стр = ЧастьВидео.ИмяЧастиTTS;
			//Стр = СтрЗаменить(Стр,"\","/");
			Если Ид = МассивЧастейВидео.Количество() Тогда
				ЗТ.ЗаписатьСтроку("""" + Стр + """"); 
			Иначе	
				ЗТ.ЗаписатьСтроку("""" + Стр + ""","); 
			КонецЕсли;	 
		КонецЦикла;
		ЗТ.ЗаписатьСтроку("],"); 
		
		
		ЗТ.ЗаписатьСтроку("""КоличествоШаговВЧастяхВидео"":["); 
		Ид = 0;
		Для каждого ЧастьВидео Из МассивЧастейВидео Цикл
			Ид = Ид + 1;
			Стр = ЧастьВидео.КоличествоШаговВДаннойЧастиВидео;
			Если Ид = МассивЧастейВидео.Количество() Тогда
				ЗТ.ЗаписатьСтроку("""" + Стр + """"); 
			Иначе	
				ЗТ.ЗаписатьСтроку("""" + Стр + ""","); 
			КонецЕсли;	 
		КонецЦикла;
		ЗТ.ЗаписатьСтроку("],"); 
		
		ЗТ.ЗаписатьСтроку("""ТипыЗначений"":["); 
		Ид = 0;
		Для каждого ЧастьВидео Из МассивЧастейВидео Цикл
			Ид = Ид + 1;
			Стр = ЧастьВидео.Тип;
			Если Ид = МассивЧастейВидео.Количество() Тогда
				ЗТ.ЗаписатьСтроку("""" + Стр + """"); 
			Иначе	
				ЗТ.ЗаписатьСтроку("""" + Стр + ""","); 
			КонецЕсли;	 
		КонецЦикла;
		ЗТ.ЗаписатьСтроку("],"); 
		
		Ид = 0;
		ЗТ.ЗаписатьСтроку("""ИменаВставок"":["); 
		Для каждого ЧастьВидео Из МассивЧастейВидео Цикл
			
			//Если ЧастьВидео.Тип <> "Вставка" Тогда
			//	Продолжить;
			//КонецЕсли;	 
			
			Ид = Ид + 1;
			ИмяВременногоФайла = ПолучитьИмяВременногоФайла("txt");
			ЗТВременногоФайла = Новый ЗаписьТекста(ИмяВременногоФайла,"UTF-8",,Истина); 
			
			Стр = СтрЗаменить(ИмяВременногоФайла,"\","/");
			Если Ид = МассивЧастейВидео.Количество() Тогда
				ЗТ.ЗаписатьСтроку("""" + Стр + """"); 
			Иначе	
				ЗТ.ЗаписатьСтроку("""" + Стр + ""","); 
			КонецЕсли;	 
			
			
			ЗТВременногоФайла.ЗаписатьСтроку(ЧастьВидео.ИмяВставки); 
			ЗТВременногоФайла.Закрыть();
		КонецЦикла;
		ЗТ.ЗаписатьСтроку("],"); 
		
	КонецЕсли;	 
	ЗТ.ЗаписатьСтроку("""ПустоеЗначение"":""ПустоеЗначение"""); 
	ЗТ.ЗаписатьСтроку("}"); 
	ЗТ.Закрыть();
	
	
	Возврат ВременныйФайл;
КонецФункции	

&НаКлиенте
Функция ПолучитьКомандуОбработатьСценарийВидео(ФайлПараметровСценария)
	
	ИмяВременногоBAT = ПолучитьИмяВременногоФайла("bat");
	ФайлПараметров = Объект.КаталогСкриптовСборкиВидео + "\StartVideo.json";
	
	Стр = "oscript " + Объект.КаталогСкриптовСборкиВидео + "\MakeScenario.os " + ФайлПараметров + " " + ФайлПараметровСценария;
	
	ЗТ = Новый ЗаписьТекста(ИмяВременногоBAT,КодировкаТекста.ANSI,,Истина); 
	ЗТ.ЗаписатьСтроку("chcp 65001");
	ЗТ.ЗаписатьСтроку(Стр); 
	ЗТ.Закрыть();
	
	Возврат ИмяВременногоBAT;
КонецФункции	

&НаКлиенте
Процедура ВыполнитьКомандуОбработатьСценарийВидео(ИД_СценарияВМассиве,НадоПрерватьСценарийДляВставки,ШагВставки)
	Если БылаОшибкаСкриптовСборкиВидео Тогда
		Возврат;
	КонецЕсли;	 
	
	
	ТекСценарий = МассивСценариевДляВыполнения[ИД_СценарияВМассиве];
	
	ФайлПараметровСценария = СоздатьФайлПараметровПоСценарию(ТекСценарий,ИД_СценарияВМассиве,НадоПрерватьСценарийДляВставки);
	
	ПутьККоманде = ПолучитьКомандуОбработатьСценарийВидео(ФайлПараметровСценария);
	
	КодВозврата = ВыполнитьСкриптСборкиВидеоБезПоказаОкна(ПутьККоманде,"ОбработатьСценарийВидео");
	Если КодВозврата <> 0 Тогда
		СделатьСообщение("Ошибка при выполнении скрипта <" + ПутьККоманде + ">! КодВозврата = " + КодВозврата);
		Возврат;
	КонецЕсли;	 
	
	ПараметрыФайла = ПрочитатьСтруктуруИзJSONФайлаКлиент(ФайлПараметровСценария);
	ИмяЧастиВидео = ПараметрыФайла["ИмяЧастиВидео"];
	ИмяЧастиСубтитры = ПараметрыФайла["ИмяЧастиСубтитры"];
	ИмяЧастиTTS      = ПараметрыФайла["ИмяЧастиTTS"];
	МассивЧастейВидео.Добавить(Новый Структура("Тип,ИмяЧастиВидео,ИмяЧастиСубтитры,ИмяЧастиTTS,КоличествоШаговВДаннойЧастиВидео,ИмяВставки","ЧастьВидео",ИмяЧастиВидео,ИмяЧастиСубтитры,ИмяЧастиTTS,КоличествоШаговВДаннойЧастиВидео,"-"));
	
	Если НадоПрерватьСценарийДляВставки Тогда
		МассивЧастейВидео.Добавить(Новый Структура("Тип,ИмяЧастиВидео,ИмяЧастиСубтитры,ИмяЧастиTTS,КоличествоШаговВДаннойЧастиВидео,ИмяВставки","Вставка","-","-","-",1,ШагВставки.ЗначенияПараметров[0].Значение.Значение));
	КонецЕсли;	 
	
	
	
	КоличествоШаговВДаннойЧастиВидео = 0;
	
	Отладка("Видео сценария создано.");

	//КомандаСистемы(Команда);
КонецПроцедуры

&НаКлиенте
Процедура ВыполнитьКомандуСкриптЗакончитьЗаписьВидео(ФайлПараметров)
	Если БылаОшибкаСкриптовСборкиВидео Тогда
		Возврат;
	КонецЕсли;	 
	
	ПутьККоманде = ПолучитьКомандуСкриптаЗакончитьЗаписьВидео(ФайлПараметров);
	КодВозврата = ВыполнитьСкриптСборкиВидеоБезПоказаОкна(ПутьККоманде,"ЗакончитьЗаписьВидео");
	Если КодВозврата <> 0 Тогда
		СделатьСообщение("Ошибка при выполнении скрипта <" + ПутьККоманде + ">! КодВозврата = " + КодВозврата);
		Возврат;
	КонецЕсли;	 
КонецПроцедуры

&НаКлиенте
Функция СоздатьПустойФайлСубтитров()
	ВременныйФайл = ПолучитьИмяВременногоФайла("txt");
	Если ФайлСуществуетКомандаСистемы(ВременныйФайл) Тогда
		УдалитьФайлыКомандаСистемы(ВременныйФайл);
	КонецЕсли;	 
	
	//ВременныйФайл = "c:\temp\333.txt";
	
	Текст = Новый ЗаписьТекста;
	Текст.Открыть(ВременныйФайл,"UTF-8");
	Текст.Закрыть();
	
	Возврат ВременныйФайл;
КонецФункции	

&НаКлиенте
Процедура НачатьЗаписьВидео()
	Если Объект.ИдетЗаписьВидео Тогда
		Возврат;
	КонецЕсли;	 
	
	Если НЕ Объект.СоздаватьИнструкциюВидео Тогда
		Возврат;
	КонецЕсли;
	
	Если Не ЗначениеЗаполнено(Объект.КаталогСкриптовСборкиВидео) Тогда
		СделатьСообщение("Не указн каталог скриптов сборки видео!");
		Возврат;
	КонецЕсли;	 
	
	Если Не ЗначениеЗаполнено(Объект.КаталогOutputИнструкцияВидео) Тогда
		ВызватьИсключение "Не указан каталог для записи ""КаталогOutputИнструкцияВидео"".";
	КонецЕсли;	 
	
	TASKKILL("vlc.exe");
	
	Объект.ИдетЗаписьВидео = Истина;
	
	ИмяФайлаСубтитров = СоздатьПустойФайлСубтитров();	
	
	Объект.ИнтервалВыполненияШага = ИнтервалВыполненияШагаПриЗаписиВидео;
	
	ВыполнитьКомандуСкриптНачатьЗаписьВидео();
	
КонецПроцедуры

&НаКлиенте
Функция ПолучитьЗначенияTTSШага(ИмяШага)
	Для каждого ЗначениеTTS Из МассивTTS Цикл
		Если ИмяШага = ЗначениеTTS.Шаг Тогда
			Возврат ЗначениеTTS;
		КонецЕсли;	 
	КонецЦикла;
	
	Возврат Неопределено;
	//ВызватьИсключение "Не смог определить ЗначениеTTS для шага: " + ИмяШага;
КонецФункции	

&НаКлиенте
Процедура ЗаписатьЛогЗаписиВидео(СтрокаТитров,ТекШаг)
	Если НЕ Объект.ИдетЗаписьВидео Тогда
		Возврат;
	КонецЕсли;	 
	
	ЗТ = Новый ЗаписьТекста(ИмяФайлаСубтитров,"UTF-8",,Истина); 
	Разделитель = "|||";
	Стр = СтрЗаменить("" + ТекущаяУниверсальнаяДатаВМиллисекундах() + Разделитель + СтрокаТитров,Символы.НПП,"");
	ЗТ.ЗаписатьСтроку(Стр); 
	ЗТ.Закрыть();
	
	ИмяШага = СокрЛП(ТекШаг.Имя);
	
	Если МассивTTS <> Неопределено Тогда
		//значит надо сделать паузу по длине файла TTS
		ЗначенияTTS = ПолучитьЗначенияTTSШага(ИмяШага);
		ЗначениеПаузы = 3;
		Если ЗначениеПаузы < ЗначенияTTS.Длительность Тогда
			ЗначениеПаузы = ЗначенияTTS.Длительность;
		КонецЕсли;	 
		
		Sleep(ЗначениеПаузы);
	КонецЕсли;	 
	
КонецПроцедуры

//работа с видео - окончание


&НаКлиенте
Функция ЭтоПрерывающйВидеоШаг(ТекШаг)
	Поз = Найти(ТекШаг.Снипет,"(");
	Стр = НРег(Лев(ТекШаг.Снипет,Поз-1));
	
	Если МассивСнипетовПрерывающихЗаписьСценария.Найти(Стр) = Неопределено Тогда
		Возврат Ложь;
	Иначе
		Возврат Истина;
	КонецЕсли;	 
КонецФункции	

&НаКлиенте
Процедура ПерейтиКВыполнениюСледующегоСценария()
	
	ЗакончитьЗаписьВидеоОдногоСценария();
	
	ТекИД_СценарияВМассиве = ТекИД_СценарияВМассиве + 1;
	ПодключитьОбработчикОжидания("ВыполнинтьСценарийАссинхронноТаймер",Объект.ИнтервалВыполненияШага,Истина);
КонецПроцедуры

&НаКлиенте
Процедура ПерейтиКВыполнениюСледующегоШага(ВыполнитьШагЧерезТаймер = Неопределено)
	Если Объект.ОстановитьВыполнениеШагов Тогда
		Возврат;
	КонецЕсли;	 
	
	Если ТекИД_СценарияВМассиве = Неопределено Тогда
		Возврат;
	КонецЕсли; 
	
	Если (ТекИД_СценарияВМассиве <> Неопределено) и (ТекИД_СценарияВМассиве >= 0) и (ТекИД_ШагаВМассиве >= 0) и (ТекИД_СценарияВМассиве <= (МассивСценариевДляВыполнения.Количество()-1) ) Тогда
		Шаги   = МассивСценариевДляВыполнения[ТекИД_СценарияВМассиве].Шаги;
		ТекШаг = Шаги[ТекИД_ШагаВМассиве];
		
		Если ТекШаг.ШагСчитаетсяУпавшим Тогда
			СтатусЗапускаСценариев = Ложь;
			
			ИДСтрокиШага                       = ТекШаг.СтрокаШага;
			ИДСтрокиСценария                   = МассивСценариевДляВыполнения[ТекИД_СценарияВМассиве].СтрокаДерева;
			РезультатПрохожденияТестовСценария = ПолучитьРезультатПрохожденияТестовСценария(ИДСтрокиСценария);
			РезультатПрохожденияТестовШагов    = РезультатПрохожденияТестовСценария.РезультатПрохожденияТестовШагов;
			
			СтрокаШага     = МассивСтрокДереваДанныеФормы[ИДСтрокиШага];
			СтрокаСценария = МассивСтрокДереваДанныеФормы[ИДСтрокиСценария];
			СтрокаШага.Статус      = "Failed";
			СтрокаШага.ТипКартинки = 5;
			СтрокаСценария.Статус  = СтрокаШага.Статус;
			АдресСнипета           = ТекШаг.АдресСнипета;
			ИмяПроцедуры           = ТекШаг.СтрокаРеальнойПроцедуры;
			
			СделатьСообщение("Шаг (" + ТекШаг.Имя + ") не выполнен.");
			ОписаниеОшибки = СформироватьОписаниеОшибки(ОписаниеОшибки(),АдресСнипета,ИмяПроцедуры);
			СделатьСообщение(ОписаниеОшибки);
			
			РезультатПрохожденияШага = РезультатПрохожденияТестовШагов[РезультатПрохожденияТестовШагов.Количество()-1];
			
			
			РезультатПрохожденияТестовСценария.Вставить("ВремяОкончания",ТекущаяУниверсальнаяДатаВМиллисекундах());
			РезультатПрохожденияТестовСценария.Вставить("ОписаниеОшибки",ОписаниеОшибки);
			РезультатПрохожденияШага.Вставить("ВремяОкончания",ТекущаяУниверсальнаяДатаВМиллисекундах());
			РезультатПрохожденияШага.Вставить("ОписаниеОшибки",ОписаниеОшибки);
			РезультатПрохожденияШага.Вставить("Статус",СтрокаШага.Статус);
			
			СделатьСообщение(ОписаниеОшибки);
			
			РезультатПрохожденияТестовШагов.Добавить(РезультатПрохожденияШага);
			
			БылаОшибка     = Ложь;
			ОписаниеОшибки = "";
			ДействияПослеЗавершенияСценария(СтрокаСценария,БылаОшибка,ОписаниеОшибки);
			
			СтрокаСценария.Статус = "Failed";
			РезультатПрохожденияТестовСценария.Вставить("ОписаниеОшибки",ОписаниеОшибки);
			ПрекратитьВыполнениШаговТакКакЗакончилсяСценарий = Истина;
			
			
			Если Объект.ДелатьСкриншотПриВозникновенииОшибки Тогда
				СделатьСкриншотВозникновенияОшибки(СтрокаШага,СтрокаСценария,РезультатПрохожденияТестовСценария);
			Иначе	
				ПерейтиКВыполнениюСледующегоСценария();
			КонецЕсли;	 

			
			
			Возврат;
		КонецЕсли;	 
	КонецЕсли;	 
	
	
	Если ТекИД_ШагаВМассиве = -1 Тогда
		ТекИД_ШагаВМассиве = ТекИД_ШагаВМассиве + 1;
	ИначеЕсли 	ТекИД_ШагаВМассиве = ТекИД_ВыполненногоШагаВМассиве Тогда // это надо т.к. в определенных случаях таймер, подключающий следующий шаг может не сработать
		ТекИД_ШагаВМассиве = ТекИД_ШагаВМассиве + 1;
	КонецЕсли;	 
	
		
	Шаги = МассивСценариевДляВыполнения[ТекИД_СценарияВМассиве].Шаги;
	Если (Шаги.Количество()-1) < ТекИД_ШагаВМассиве Тогда
		//значит все шаги выполнены, запускаем следующий сценарий
		//МассивСценариевДляВыполнения[ТекИД_СценарияВМассиве].СтрокаДерева.ВремяОкончания = ТекущаяУниверсальнаяДатаВМиллисекундах();
		
		ИДСтрокиСценария                   = МассивСценариевДляВыполнения[ТекИД_СценарияВМассиве].СтрокаДерева;
		СтрокаСценария = МассивСтрокДереваДанныеФормы[ИДСтрокиСценария];
		
		БылаОшибка     = Ложь;
		ОписаниеОшибки = "";
		ДействияПослеЗавершенияСценария(СтрокаСценария,БылаОшибка,ОписаниеОшибки);
		
		РезультатПрохожденияТестовСценария = ПолучитьРезультатПрохожденияТестовСценария(ИДСтрокиСценария);
		РезультатПрохожденияТестовСценария.Вставить("ВремяОкончания",ТекущаяУниверсальнаяДатаВМиллисекундах());
		ПрекратитьВыполнениШаговТакКакЗакончилсяСценарий = Истина;
		
		Если БылаОшибка Тогда
			СтатусЗапускаСценариев = Ложь;		
			СтрокаСценария.Статус  = "Failed";
			РезультатПрохожденияТестовСценария.Вставить("ОписаниеОшибки",ОписаниеОшибки);
		КонецЕсли;
		
		Если СтрокаСценария.Статус = "Failed" и Объект.ДелатьСкриншотПриВозникновенииОшибки Тогда
			СделатьСкриншотВозникновенияОшибки("ПередОкончаниемСценария",СтрокаСценария,РезультатПрохожденияТестовСценария);
		Иначе	
			
			ПерейтиКВыполнениюСледующегоСценария();
		КонецЕсли;	 
		
		
		Возврат;
	КонецЕсли;	 
	
	
	
	
	Если ТекИД_ШагаВМассиве >= 0 Тогда
		//логируем выполненный шаг
		ТекШаг = Шаги[ТекИД_ШагаВМассиве];
		
		
		Если НЕ ТекШаг.ЭтоШагКонтекста Тогда
			НачатьЗаписьВидео();
			
			Если Объект.ИдетЗаписьВидео Тогда
				СтрокаТитров = ТекШаг.Имя;
				Если ТекШаг.ШагСПараметрамиВТаблице = Истина Тогда
					Для каждого СтрПараметрыТаблицы Из ТекШаг.ПараметрыТаблицы Цикл
						СтрокаТитров = СтрокаТитров + "\n" + СтрПараметрыТаблицы;
					КонецЦикла;
				КонецЕсли;	 
				
				Если ЭтоПрерывающйВидеоШаг(ТекШаг) Тогда
					ИДВставкиВВидео = ИДВставкиВВидео + 1;
					ЗакончитьЗаписьВидеоОдногоСценария(Истина,ТекШаг);
					НачатьЗаписьВидео();
				Иначе	
					ЗаписатьЛогЗаписиВидео(СтрокаТитров,ТекШаг);
				КонецЕсли;	 
				
				
				
				
			КонецЕсли;	 
		КонецЕсли;	 
	КонецЕсли;	 
	
	
	
	Шаги = МассивСценариевДляВыполнения[ТекИД_СценарияВМассиве].Шаги;
	Если (Шаги.Количество()-1) >= ТекИД_ШагаВМассиве Тогда
		СтрокаШага                          = МассивСтрокДереваДанныеФормы[Шаги[ТекИД_ШагаВМассиве].СтрокаШага];
		Элементы.ДеревоТестов.ТекущаяСтрока = СтрокаШага.ПолучитьИдентификатор();
	КонецЕсли;
	
	
	
	
	ИнтервалДляВыполненияШага = Объект.ИнтервалВыполненияШага;
	Если Объект.ИдетЗаписьВидео Тогда
		Если ЭтоПрерывающйВидеоШаг(ТекШаг) Тогда
			ИнтервалДляВыполненияШага = 0.1;
		КонецЕсли;	 
		
		Если ТекШаг.ЭтоШагКонтекста Тогда
			ИнтервалДляВыполненияШага = 0.1;
		КонецЕсли;	 
		
		Если МассивTTS <> Неопределено Тогда
			ИнтервалДляВыполненияШага = 0.1;
		КонецЕсли;	 
		
	КонецЕсли;	 
	
	
	
	
	Если (ВыполнитьШагЧерезТаймер = Истина) Тогда
		ПодключитьОбработчикОжидания("ВыполнитьШаг",ИнтервалДляВыполненияШага,Истина); //вызвываем шаг через таймер, чтобы дать всем формам прорисоваться
	ИначеЕсли (НЕ Объект.ВыполнятьШагиАссинхронно)  Тогда 
		ВыполнитьШаг();//просто вызываем следующий шаг
	Иначе
		ПодключитьОбработчикОжидания("ВыполнитьШаг",ИнтервалДляВыполненияШага,Истина); //вызвываем шаг через таймер, чтобы дать всем формам прорисоваться
	КонецЕсли;
	
КонецПроцедуры

&НаКлиенте
Процедура ДобавитьШагиВРезультатПрохожденияТестовШаговКоторыеНеВыполнялись(Шаги,ТекИД,РезультатПрохожденияТестовШагов)
	Ид = ТекИД;
	Пока Истина Цикл
		Ид = Ид+1;
		Если Шаги.Количество() < (Ид+1) Тогда
			Прервать;
		КонецЕсли;	 
		
		ТекШаг = Шаги[Ид];
		
		РезультатПрохожденияШага = Новый Структура;
		РезультатПрохожденияШага.Вставить("Имя",ТекШаг.Имя);
		РезультатПрохожденияШага.Вставить("ВремяНачала",ТекущаяУниверсальнаяДатаВМиллисекундах());
		РезультатПрохожденияШага.Вставить("ВремяОкончания",ТекущаяУниверсальнаяДатаВМиллисекундах());
		РезультатПрохожденияШага.Вставить("ОписаниеОшибки","Пропущен");
		РезультатПрохожденияШага.Вставить("Статус","Skipped");
		
		РезультатПрохожденияТестовШагов.Добавить(РезультатПрохожденияШага);
		
	КонецЦикла;
КонецПроцедуры

&НаКлиенте
Функция ОпределитьИмяФичаФайлаПоСтрокеДерева(СтрокаДерева)
	Если СтрокаДерева.Фича = Истина Тогда
		Возврат СтрокаДерева.ПолныйПуть;
	КонецЕсли;	 
	
	Возврат ОпределитьИмяФичаФайлаПоСтрокеДерева(СтрокаДерева.ПолучитьРодителя());
КонецФункции	

&НаКлиенте
Функция ПолучитьКонтекстТестаПоАдресСнипета(АдресСнипета)
	ИД = МассивИменКонтекстовОбработок.Найти(АдресСнипета);
	Если ИД = Неопределено Тогда
		//Скорее всего это обработка не содержащая в себе тесты.
		Возврат Неопределено;
	Иначе
		ОбработкаТеста = ТаблицаКонтекстовОбработок[ИД].Обработка;
	КонецЕсли;	 
	
	Возврат ОбработкаТеста;
КонецФункции	

&НаКлиенте
Процедура ВызватьМетодСценарияЕслиОнЕсть(СтрокаДереваСценария, ИмяПроцедуры,МассивПараметров = Неопределено,БылаОшибка = Ложь,ОписаниеОшибки = Неопределено)
	ИмяФичаФайла = ОпределитьИмяФичаФайлаПоСтрокеДерева(СтрокаДереваСценария);
	Если ИмяФичаФайла = Неопределено Тогда
		Возврат;
	КонецЕсли;	
	
	Файл         = Новый Файл(ИмяФичаФайла);
	КаталогФичи  = Файл.Путь;
	АдресСнипета = ДополнитьСлешВПуть(КаталогФичи) + ДополнитьСлешВПуть("step_definitions") + Файл.ИмяБезРасширения + ".epf";
	
	
	ФайлПроверкаСуществования = Новый Файл(АдресСнипета);
	Если НЕ СтрокаДереваСценария.ФичаИмеетСвоюEPF Тогда
		Возврат;
	КонецЕсли;	 
	
	ОбработкаТеста = ПолучитьКонтекстТестаПоАдресСнипета(АдресСнипета);
	Если ОбработкаТеста = Неопределено Тогда
		//это возможно, если у фичи вообще нет своей обработки и она использует только шаги из других фич
		Возврат;
	КонецЕсли;  
	
	ОбработкаТеста.Контекст            = ОбъектКонтекст;
	ОбработкаТеста.КонтекстСохраняемый = ОбъектКонтекстСохраняемый;
	
	Попытка
		ВызватьМетод(ОбработкаТеста, ИмяПроцедуры, МассивПараметров);
	Исключение
		Сообщить("Ошибка в " + ИмяПроцедуры + ". " + ОписаниеОшибки());
		БылаОшибка     = Истина;
		ОписаниеОшибки = ОписаниеОшибки();
	КонецПопытки;
	
	ОбъектКонтекст            = ОбработкаТеста.Контекст;
	ОбъектКонтекстСохраняемый = ОбработкаТеста.КонтекстСохраняемый;
	
КонецПроцедуры

&НаКлиенте
Процедура ПодготовитьСозданиеИнструкцииHTML()
	Если НЕ Объект.СоздаватьИнструкциюHTML Тогда
		Возврат;
	КонецЕсли;	
	
	//ФайлПроверкаСуществования = Новый Файл(Объект.КаталогOutputИнструкцияHTML);
	//Если НЕ ФайлПроверкаСуществования.Существует() Тогда
	Если НЕ ФайлСуществуетКомандаСистемы(Объект.КаталогOutputИнструкцияHTML) Тогда 
		Стр = "Файл КаталогOutputИнструкцияHTML: " + Объект.КаталогOutputИнструкцияHTML + " не существует!";
		Сообщить(Стр);
		ВызватьИсключение Стр;
	КонецЕсли;	 
	
	Если Найти(Прав(Объект.КаталогOutputИнструкцияHTML,1), "\/") > 0 Тогда
		Объект.КаталогOutputИнструкцияHTML = Сред(Объект.КаталогOutputИнструкцияHTML,СтрДлина(Объект.КаталогOutputИнструкцияHTML)-1);
	КонецЕсли;	 
	
	Если МассивСценариевДляВыполнения.Количество() = 0 Тогда
		Возврат;
	КонецЕсли;
	
	Если ТекущаяФичаИнструкцииHTML <> МассивСценариевДляВыполнения[ТекИД_СценарияВМассиве].ИмяФичи Тогда
		Если ТекущаяФичаИнструкцииHTML <> "" Тогда
			СоздатьФайлHTMLИнструкции();
		КонецЕсли;  
		ТекущаяФичаИнструкцииHTML = МассивСценариевДляВыполнения[ТекИД_СценарияВМассиве].ИмяФичи;
	Иначе
		Возврат;
	КонецЕсли;  
	
	ИмяФайлаЛогаИнструкцииHTML = СтрЗаменить(Объект.КаталогOutputИнструкцияHTML + "/InstrHTML_" + ТекущаяФичаИнструкцииHTML + "_" +  СтрЗаменить(СтрЗаменить(ТекущаяДата(),":","")," ","_") + "_" + ТекущаяУниверсальнаяДатаВМиллисекундах() + "_log.txt",Символы.НПП,"");
	
	ТД = Новый ТекстовыйДокумент;
	ЗаголовокФичи = ПрочитатьЗаголовокФичи(МассивСценариевДляВыполнения[ТекИД_СценарияВМассиве].ПолныйПутьКФиче);
	ТД = Новый ТекстовыйДокумент;
	Для каждого Стр Из ЗаголовокФичи Цикл
		ТД.ДобавитьСтроку(Стр);
	КонецЦикла;
	ТД.ДобавитьСтроку("--окончание заголовка--");
	ТД.Записать(ИмяФайлаЛогаИнструкцииHTML,КодировкаТекста.UTF8);
	
КонецПроцедуры

Функция ПрочитатьЗаголовокФичи(ИмяФайла)
	Массив = Новый Массив;
	
	Текст = Новый ЧтениеТекста;
	Текст.Открыть(ИмяФайла,"UTF-8");
	
	Пока Истина Цикл
		Стр = Текст.ПрочитатьСтроку();
		Если Стр = Неопределено Тогда
			Прервать;
		КонецЕсли;	 
		
		Если СокрЛП(Стр) = "" Тогда
			Продолжить;
		КонецЕсли;	 
		
		Стр = СокрЛП(Стр);
		
		Если Лев(Стр,1) = "@" Тогда
			Продолжить;
		КонецЕсли;	 
		Если Лев(Стр,1) = "#" Тогда
			Продолжить;
		КонецЕсли;	 
		
		Если Найти(НРег(Стр),"сценарий:") > 0 Тогда
			Прервать;
		КонецЕсли;	 
		Если Найти(НРег(Стр),"контекст:") > 0 Тогда
			Прервать;
		КонецЕсли;	 
		
		Массив.Добавить(Стр);
		
	КонецЦикла;	
	
	Текст.Закрыть();
	
	Возврат Массив;
КонецФункции	

&НаКлиенте
Процедура ПодготовитьСозданиеИнструкцииMarkdown()
	Если НЕ Объект.СоздаватьИнструкциюMarkdown Тогда
		Возврат;
	КонецЕсли;	
	
	Если НЕ ФайлСуществуетКомандаСистемы(Объект.КаталогOutputИнструкцияMarkdown) Тогда 
		Стр = "Файл КаталогOutputИнструкцияMarkdown: " + Объект.КаталогOutputИнструкцияMarkdown + " не существует!";
		Сообщить(Стр);
		ВызватьИсключение Стр;
	КонецЕсли;	 
	
	Если Найти(Прав(Объект.КаталогOutputИнструкцияMarkdown,1), "\/") > 0 Тогда
		Объект.КаталогOutputИнструкцияMarkdown = Сред(Объект.КаталогOutputИнструкцияMarkdown,СтрДлина(Объект.КаталогOutputИнструкцияMarkdown)-1);
	КонецЕсли;	 
	
	Если МассивСценариевДляВыполнения.Количество() = 0 Тогда
		Возврат;
	КонецЕсли;
	
	Если ТекущаяФичаИнструкцииMarkdown <> МассивСценариевДляВыполнения[ТекИД_СценарияВМассиве].ИмяФичи Тогда
		Если ТекущаяФичаИнструкцииMarkdown <> "" Тогда
			СоздатьФайлMarkdownИнструкции();
		КонецЕсли;  
		ТекущаяФичаИнструкцииMarkdown = МассивСценариевДляВыполнения[ТекИД_СценарияВМассиве].ИмяФичи;
	Иначе
		Возврат;
	КонецЕсли;  
	
	ИмяФайлаЛогаИнструкцииMarkdown = СтрЗаменить(Объект.КаталогOutputИнструкцияMarkdown + "/InstrMarkdown_" + ТекущаяФичаИнструкцииMarkdown + "_" +  СтрЗаменить(СтрЗаменить(ТекущаяДата(),":","")," ","_") + "_" + ТекущаяУниверсальнаяДатаВМиллисекундах() + "_log.txt",Символы.НПП,"");
	
	ЗаголовокФичи = ПрочитатьЗаголовокФичи(МассивСценариевДляВыполнения[ТекИД_СценарияВМассиве].ПолныйПутьКФиче);
	ТД = Новый ТекстовыйДокумент;
	Для каждого Стр Из ЗаголовокФичи Цикл
		ТД.ДобавитьСтроку(Стр);
	КонецЦикла;
	ТД.ДобавитьСтроку("--окончание заголовка--");
	ТД.Записать(ИмяФайлаЛогаИнструкцииMarkdown,КодировкаТекста.UTF8);
	
КонецПроцедуры

&НаСервере
Процедура СформироватьОтчетАллюрСервер(СтруктураОФ)
	ОбъектСервер = РеквизитФормыВЗначение("Объект");
	Дерево = ОбъектСервер.ДеревоТестов;
	
	ОбъектСервер.СформироватьОтчетАллюр(СтруктураОФ);
	
КонецПроцедуры

&НаСервере
Процедура СформироватьОтчетxUnitСервер(СтруктураОФ)
	ОбъектСервер = РеквизитФормыВЗначение("Объект");
	ОбъектСервер.СформироватьОтчетxUnit(СтруктураОФ);
КонецПроцедуры

&НаКлиенте
Процедура ВыгрузитьСтатусВыполненияСценариевВФайл(Статус,ПутьКФайлу)
	Файл = Новый Файл(ПутьКФайлу);
	
	Если НЕ ЕстьПоддержкаАсинхронныхВызовов Тогда
		Если ФайлСуществуетКомандаСистемы(Файл.ПолноеИмя) Тогда
			Если Файл.ЭтоКаталог() Тогда
				СделатьСообщение("Не могу выгрузить статус сценариев, т.к. был передан каталог, а не файл.");
				Возврат;
			КонецЕсли;	
		КонецЕсли;	 
	КонецЕсли;	 
	
	
	ФайлКаталог = Новый Файл(Файл.Путь);
	Если НЕ ФайлСуществуетКомандаСистемы(ФайлКаталог.ПолноеИмя) Тогда
		СделатьСообщение("Не могу выгрузить статус сценариев, т.к. каталог " + ФайлКаталог.ПолноеИмя + " не существует!");
		Возврат;
	КонецЕсли;	
	
	УдалитьФайлыКомандаСистемы(ПутьКФайлу);
	
	ЗТ = Новый ЗаписьТекста(ПутьКФайлу,"UTF-8",,Истина); 
	Если Статус Тогда
		Стр = "0";
	Иначе	
		Стр = "1";
	КонецЕсли;	 
	
	ЗТ.ЗаписатьСтроку(Стр); 
	
	ЗТ.Закрыть();
	
	СделатьСообщение("Записал файл статуса билда: " + ПутьКФайлу);
КонецПроцедуры

&НаКлиенте
Процедура ЗакрытьTestClientЕслиОнПодключен()
	Попытка
		ОбъектКонтекстСохраняемый.ГлавноеОкноТестируемого.Закрыть();
	Исключение
		
	КонецПопытки;
КонецПроцедуры


&НаКлиенте
Функция ПолучитьОбработкаСвязаннаяСИсполняемойФичей(ИмяФайлаФичи)
	ФайлФичи = Новый Файл(ИмяФайлаФичи);
	ФайлEPF  = ФайлФичи.Путь + "step_definitions" +?(ЭтоLinux, "/", "\") + ФайлФичи.ИмяБезРасширения + ".epf";
	ИД       = МассивИменКонтекстовОбработок.Найти(ФайлEPF);
	Возврат ТаблицаКонтекстовОбработок[ИД].Обработка;
КонецФункции




&НаКлиенте
Процедура ВыполнинтьСценарийАссинхронноТаймер()
	Объект.ИнтервалВыполненияШага = Объект.ИнтервалВыполненияШагаЗаданныйПользователем;
	
	ОбъектКонтекст = Новый Структура;
	ЭтаФорма.ТекущийЭлемент = Элементы.ГруппаЗапускТестов;
	
	Если ТекИД_СценарияВМассиве > 0 Тогда
		ОбработатьСтатусСценария(ТекИД_СценарияВМассиве-1);
	КонецЕсли; 
	
	ПрекратитьВыполнениШаговТакКакЗакончилсяСценарий = Ложь;
	ИДВставкиВВидео                                  = 0;
	МассивЧастейВидео                                = Новый Массив;
	КоличествоШаговВДаннойЧастиВидео                 = 0;
	
	Если (МассивСценариевДляВыполнения.Количество()-1) < ТекИД_СценарияВМассиве Тогда
		//Сообщить(" ");
		
		СоздатьФайлHTMLИнструкции();
		СоздатьФайлMarkdownИнструкции();
		СделатьОдинФайлВидеоПоЗаписаннымДанным();
		
		СделатьСообщение("Все сценарии обработаны!");
		Если Объект.ДелатьОтчетВФорматеАллюр Тогда
			СтруктураОФ = Новый Структура;
			СтруктураОФ.Вставить("МассивРезультатПрохожденияТестовСценария",МассивРезультатПрохожденияТестовСценария);
			СтруктураОФ.Вставить("МассивИДСтрокиДерева",МассивИДСтрокиДерева);
			
			
			ДвоичныеДанные = Новый ДвоичныеДанные(Объект.КаталогИнструментов + "/vendor/allure-framework/allure.xsd");
			СтруктураОФ.Вставить("СхемаAllure",ДвоичныеДанные);
			СтруктураОФ.Вставить("ЕстьПоддержкаАсинхронныхВызовов",ЕстьПоддержкаАсинхронныхВызовов);
			
			СформироватьОтчетАллюрСервер(СтруктураОФ);
			
			Если Объект.ДелатьСкриншотПриВозникновенииОшибки Тогда
				Для каждого РезультатПрохожденияТестовСценария Из МассивРезультатПрохожденияТестовСценария Цикл
					Если Не РезультатПрохожденияТестовСценария.Свойство("МассивСкриншотов") Тогда
						Продолжить;
					КонецЕсли;	 
					
					Для каждого СтруктураСкриншот Из РезультатПрохожденияТестовСценария.МассивСкриншотов Цикл
						ВременныйФайл = ПолучитьИмяВременногоФайла("png");
						СтруктураСкриншот.ДвоичныеДанные.Записать(ВременныйФайл);
						КопироватьФайлКомандаСистемы(ВременныйФайл,Объект.КаталогOutputAllure + "\" + СтруктураСкриншот.ИмяФайла);
					КонецЦикла;
				КонецЦикла;
			КонецЕсли;	 
			
			
			
			
			Если СтруктураОФ.Свойство("МассивXMLОтчетаAllure") Тогда 
				МассивXMLОтчетаAllure = СтруктураОФ.МассивXMLОтчетаAllure;
				Для каждого Элем Из МассивXMLОтчетаAllure Цикл
					ИмяФайлаXML           = ДополнитьСлешВПуть(Объект.КаталогOutputAllure) + Элем.РеальноеИмяФайла;
					ФайлXMLДвоичныеДанные = Элем.ФайлXMLДвоичныеДанные;
					ФайлXMLДвоичныеДанные.Записать(ИмяФайлаXML);
					
					СделатьСообщение("Файл отчета Allure-report (" + ИмяФайлаXML + ") записан.");
				КонецЦикла;
			КонецЕсли;
		КонецЕсли; 	
		
		Если Объект.ДелатьОтчетВФорматеxUnit Тогда
			СтруктураОФ = Новый Структура;
			СтруктураОФ.Вставить("МассивРезультатПрохожденияТестовСценария",МассивРезультатПрохожденияТестовСценария);
			СтруктураОФ.Вставить("МассивИДСтрокиДерева",МассивИДСтрокиДерева);
			
			ДвоичныеДанные = Новый ДвоичныеДанные(Объект.КаталогИнструментов + "/vendor/allure-framework/allure.xsd");
			СтруктураОФ.Вставить("СхемаAllure",ДвоичныеДанные);
			СтруктураОФ.Вставить("ЕстьПоддержкаАсинхронныхВызовов",ЕстьПоддержкаАсинхронныхВызовов);
						
			СформироватьОтчетxUnitСервер(СтруктураОФ);
			
			Если СтруктураОФ.Свойство("МассивXMLОтчетаxUnit") Тогда 
				МассивXMLОтчетUnit = СтруктураОФ.МассивXMLОтчетаxUnit;
				Для каждого Элем Из МассивXMLОтчетUnit Цикл
					ИмяФайлаXML           = ДополнитьСлешВПуть(Объект.КаталогOutputxUnit) + Элем.РеальноеИмяФайла;
					ФайлXMLДвоичныеДанные = Элем.ФайлXMLДвоичныеДанные;
					ФайлXMLДвоичныеДанные.Записать(ИмяФайлаXML);
					
					СделатьСообщение("Файл отчета xUnit-report (" + ИмяФайлаXML + ") записан.");
				КонецЦикла;
			КонецЕсли;

			
			
			//МассивXMLОтчетаAllure = СтруктураОФ.МассивXMLОтчетаAllure;
			//Для каждого Элем Из МассивXMLОтчетаAllure Цикл
			//	ИмяФайлаXML           = ДополнитьСлешВПуть(Объект.КаталогOutputAllure) + Элем.РеальноеИмяФайла;
			//	ФайлXMLДвоичныеДанные = Элем.ФайлXMLДвоичныеДанные;
			//	ФайлXMLДвоичныеДанные.Записать(ИмяФайлаXML);
			//	
			//	СделатьСообщение("Файл отчета Allure-report (" + ИмяФайлаXML + ") записан.");
			//КонецЦикла;
			
		КонецЕсли; 
		
		Если Объект.ДелатьОтчетВоВнутреннемФормате Тогда
			//Сформируем отчет для показа пользователю. 
			СтруктураОФ = Новый Структура;
			СтруктураОФ.Вставить("МассивРезультатПрохожденияТестовСценария",МассивРезультатПрохожденияТестовСценария);
			СтруктураОФ.Вставить("МассивИДСтрокиДерева",МассивИДСтрокиДерева);
			
			Если НЕ Объект.ЗапускИзКоманднойСтроки Тогда
				ТабличныйДокумент = СформироватьОтчетВоВнутреннемФормате(СтруктураОФ);
				ТабличныйДокумент.Показать();
			КонецЕсли; 
			
		КонецЕсли; 
		
		Если Объект.ВыгружатьСтатусВыполненияСценариевВФайл Тогда
			ВыгрузитьСтатусВыполненияСценариевВФайл(СтатусЗапускаСценариев,Объект.ПутьКФайлуДляВыгрузкиСтатусаВыполненияСценариев);
		КонецЕсли;	 
		
		Если Объект.ЗакрытьTestClientПослеЗапускаСценариев Тогда
			ЗакрытьTestClientЕслиОнПодключен();
		КонецЕсли;	 
		
		
		Если Объект.НадоЗавершитьРаботуСистемыПослеВыполненияВсехСценариев Тогда
			ЗавершитьРаботуСистемы(Ложь);
		КонецЕсли;	 
		
		Возврат;
	КонецЕсли;	 
	
	ПодготовитьСозданиеИнструкцииHTML();
	ПодготовитьСозданиеИнструкцииMarkdown();
	
	Сообщить(" ");
	СделатьСообщение("Работаю по сценарию: " + МассивСценариевДляВыполнения[ТекИД_СценарияВМассиве].Имя);
	
	Если Объект.ДелатьЛогВыполненияСценариевВЖР Тогда
		ЗаписатьЛогВЖРПередВыполнениемСценария(МассивСценариевДляВыполнения[ТекИД_СценарияВМассиве].Имя);
	КонецЕсли;	 
	
	
	ИДСтроки = МассивСценариевДляВыполнения[ТекИД_СценарияВМассиве].СтрокаДерева;
	
	РезультатПрохожденияТестовСценария = Новый Структура;
	РезультатПрохожденияТестовСценария.Вставить("ИДСтроки",ИДСтроки);
	РезультатПрохожденияТестовСценария.Вставить("ВремяНачала",ТекущаяУниверсальнаяДатаВМиллисекундах());
	РезультатПрохожденияТестовШагов = Новый Массив;
	РезультатПрохожденияТестовСценария.Вставить("РезультатПрохожденияТестовШагов",РезультатПрохожденияТестовШагов);
	
	ДобавитьРезультатПрохожденияТестовСценарияВМассив(РезультатПрохожденияТестовСценария,ИДСтроки);
	
	ИДСтрокиСценария = МассивСценариевДляВыполнения[ТекИД_СценарияВМассиве].СтрокаДерева;
	СтрокаСценария = МассивСтрокДереваДанныеФормы[ИДСтрокиСценария];
	Элементы.ДеревоТестов.ТекущаяСтрока = СтрокаСценария.ПолучитьИдентификатор();
	
	
	ОбработкаСвязаннаяСИсполняемойФичей = Неопределено;
	Если СтрокаСценария.ФичаИмеетСвоюEPF Тогда
		СтрокаФичи = НайтиСтрокуФичиЧерезРодителя(СтрокаСценария);
		ОбработкаСвязаннаяСИсполняемойФичей = ПолучитьОбработкаСвязаннаяСИсполняемойФичей(СтрокаФичи.ПолныйПуть);
	КонецЕсли; 
	
	
	ДобавитьВЛогИнструкцииHTMLНачалоСценария(МассивСценариевДляВыполнения[ТекИД_СценарияВМассиве]);
	ДобавитьВЛогИнструкцииMarkdownНачалоСценария(МассивСценариевДляВыполнения[ТекИД_СценарияВМассиве]);
	
	
	ТекИД_ШагаВМассиве             = -1;
	ТекИД_ВыполненногоШагаВМассиве = -1;
	ВсёЕщёИдётВыполнениеШагов      = 0;
	
	
	БылаОшибка = Ложь;
	ОписаниеОшибки = "";
	ВызватьМетодСценарияЕслиОнЕсть(СтрокаСценария, "ПередНачаломСценария",,БылаОшибка,ОписаниеОшибки);
	Если БылаОшибка Тогда
		СтатусЗапускаСценариев = Ложь;		
		
		ИДСтрокиСценария      = МассивСценариевДляВыполнения[ТекИД_СценарияВМассиве].СтрокаДерева;
		СтрокаСценария        = МассивСтрокДереваДанныеФормы[ИДСтрокиСценария];
		СтрокаСценария.Статус = "Failed";
		
		ДействияПослеЗавершенияСценария(СтрокаСценария);
		РезультатПрохожденияТестовСценария = ПолучитьРезультатПрохожденияТестовСценария(ИДСтрокиСценария);
		РезультатПрохожденияТестовСценария.Вставить("ВремяОкончания",ТекущаяУниверсальнаяДатаВМиллисекундах());
		РезультатПрохожденияТестовСценария.Вставить("ОписаниеОшибки",ОписаниеОшибки);
		ПрекратитьВыполнениШаговТакКакЗакончилсяСценарий = Истина;
		
		
		Если Объект.ДелатьСкриншотПриВозникновенииОшибки Тогда
			СделатьСкриншотВозникновенияОшибки("ПередНачаломСценария",СтрокаСценария,РезультатПрохожденияТестовСценария);
		Иначе	
			ПерейтиКВыполнениюСледующегоСценария();
		КонецЕсли;	 

		
		Возврат;
	КонецЕсли;	 
	
	ПерейтиКВыполнениюСледующегоШага();
	
КонецПроцедуры

&НаКлиенте
Процедура ДобавитьВЛогИнструкцииHTMLНачалоСценария(СтруктураСценария)
	Если НЕ Объект.СоздаватьИнструкциюHTML Тогда
		Возврат;
	КонецЕсли;  
	
	ТД = Новый ТекстовыйДокумент();
	ТД.Прочитать(ИмяФайлаЛогаИнструкцииHTML,КодировкаТекста.UTF8);
	
	ТД.ДобавитьСтроку("НачалоСценария");
	ТД.ДобавитьСтроку("ИмяСценария=" + СтруктураСценария.Имя);
	ТД.ДобавитьСтроку("ИмяФичи=" + СтруктураСценария.ИмяФичи);
	
	ТД.Записать(ИмяФайлаЛогаИнструкцииHTML,КодировкаТекста.UTF8);
КонецПроцедуры

&НаКлиенте
Процедура ДобавитьВЛогИнструкцииMarkdownНачалоСценария(СтруктураСценария)
	Если НЕ Объект.СоздаватьИнструкциюMarkdown Тогда
		Возврат;
	КонецЕсли;  
	
	ТД = Новый ТекстовыйДокумент();
	ТД.Прочитать(ИмяФайлаЛогаИнструкцииMarkdown,КодировкаТекста.UTF8);
	
	ТД.ДобавитьСтроку("НачалоСценария");
	ТД.ДобавитьСтроку("ИмяСценария=" + СтруктураСценария.Имя);
	ТД.ДобавитьСтроку("ИмяФичи=" + СтруктураСценария.ИмяФичи);
	
	ТД.Записать(ИмяФайлаЛогаИнструкцииMarkdown,КодировкаТекста.UTF8);
КонецПроцедуры

&НаКлиенте
Процедура ДобавитьРезультатПрохожденияТестовСценарияВМассив(РезультатПрохожденияТестовСценария,ИДСтроки)
	ИД = МассивИДСтрокиДерева.Найти(ИДСтроки);
	Если ИД = Неопределено Тогда
		МассивИДСтрокиДерева.Добавить(ИДСтроки);
		МассивРезультатПрохожденияТестовСценария.Добавить(РезультатПрохожденияТестовСценария);
	Иначе
		МассивРезультатПрохожденияТестовСценария[ИД] = РезультатПрохожденияТестовСценария;
	КонецЕсли;	 
	
КонецПроцедуры

&НаКлиенте
Процедура ЗапомнитьСтрокиДереваДанныеФормыРекурсивно(ДеревоФормы)
	Для каждого ЭлементДерева Из ДеревоФормы Цикл
		ИДСтроки = ЭлементДерева.ИДСтроки;
		МассивСтрокДереваДанныеФормы[ИДСтроки] = ЭлементДерева;
		
		ЗапомнитьСтрокиДереваДанныеФормыРекурсивно(ЭлементДерева.ПолучитьЭлементы());
	КонецЦикла;
КонецПроцедуры

&НаКлиенте
Процедура ЗапомнитьСтрокиДереваДанныеФормы()
	ДеревоФормы = Объект.ДеревоТестов.ПолучитьЭлементы();
	ЗапомнитьСтрокиДереваДанныеФормыРекурсивно(ДеревоФормы);
КонецПроцедуры


&НаСервере
Функция ОпределитьИдСценарияПоСтрокеШага(ИдСтроки)
	Если ИдСтроки = Неопределено Тогда
		Возврат Неопределено;
	КонецЕсли;	 
	
	ОбъектСервер = РеквизитФормыВЗначение("Объект");
	
	Дерево = ОбъектСервер.ДеревоТестов;
	
	СтрокаДерева = Дерево.Строки.Найти(ИдСтроки,"ИдСтроки",Истина);
	Если СтрокаДерева = Неопределено Тогда
		Возврат Неопределено;
	КонецЕсли;	 
	
	Возврат СтрокаДерева.Родитель.ИДСтроки;
КонецФункции	

&НаКлиенте
Процедура ВыполнитьСценарии(ТекСценарий = Неопределено) Экспорт
	ОчиститьСообщения();
	БылаОшибкаСкриптовСборкиВидео = Ложь;
	Объект.ОстановитьВыполнениеШагов = Ложь;
	Объект.ИдетЗаписьВидео           = Ложь;
	
	СтатусЗапускаСценариев    = Истина;
	ОчиститьПоляВДеревеДляПостроенияОтчетовСервер();
	
	МассивИДСтрокиДерева                     = Новый Массив;
	МассивРезультатПрохожденияТестовСценария = Новый Массив;
	
	МассивСценариевДляВыполнения = Новый Массив;
	МассивСтрокДереваДанныеФормы = Новый Массив;
	
	ЕстьСохранённыйКонтекст = Ложь;
	Если (ТекСценарий = Неопределено) и (Объект.РежимВыполненияСценарияСВыбранногоШага) Тогда
		ТекСценарий          = ОпределитьИдСценарияПоСтрокеШага(СтрокаШагаСКоторогоНадоВыполнятьСценарий.ИдСтроки);
		СохраненнаяСтруктура = ПолучитьСостоянияКонтекстовПоИдСтроки(СтрокаШагаСКоторогоНадоВыполнятьСценарий.ИдСтроки);
		Если СохраненнаяСтруктура <> Неопределено Тогда //значит есть сохранённый контекст
			ЕстьСохранённыйКонтекст = Истина;
		КонецЕсли;	 
	КонецЕсли;	 
	
	ДопПараметры = Новый Структура;
	ДопПараметры.Вставить("РежимВыполненияСценарияСВыбранногоШага",Объект.РежимВыполненияСценарияСВыбранногоШага и ЕстьСохранённыйКонтекст);
	Если Объект.РежимВыполненияСценарияСВыбранногоШага Тогда
		ДопПараметры.Вставить("ИдСтрокиШагаСКоторогоВыполнятьСценарий",СтрокаШагаСКоторогоНадоВыполнятьСценарий.ИдСтроки);
	КонецЕсли;	 
	ЗаполнитьМассивСценариевДляВыполненияСервер(МассивСценариевДляВыполнения,МассивСтрокДереваДанныеФормы,ТекСценарий,МассивИменКонтекстовОбработок,ДопПараметры);
	
	ЗапомнитьСтрокиДереваДанныеФормы();
	
	ТекущаяФичаИнструкцииHTML     = "";
	ТекущаяФичаИнструкцииMarkdown = "";
	Если НЕ ПроверитьНаличиеИнструментаДляСозданияСкриншотов() Тогда
		Возврат;
	КонецЕсли;  
	
	Если Объект.ДелатьСкриншотПриВозникновенииОшибки Тогда
		Если Не ЗначениеЗаполнено(Объект.КомандаСделатьСкриншот) Тогда
			СделатьСообщение("Не указана команада для выполнения скриншотов! Например <""C:\Program Files (x86)\IrfanView\i_view32.exe"" /capture=1 /convert=>");
			Возврат;
		КонецЕсли;	 
		ОчиститьСодержимоеКаталога(Объект.КаталогOutputСкриншоты);
	КонецЕсли;	 
	
	
	Если Объект.СоздаватьИнструкциюВидео Тогда
		ОчиститьСодержимоеКаталога(Объект.КаталогOutputИнструкцияВидео);
		ВыполнитьПодготовкуКЗаписиВидео();
	КонецЕсли;	 
	
	Если Объект.СоздаватьИнструкциюHTML Тогда
		ОчиститьСодержимоеКаталога(Объект.КаталогOutputИнструкцияHTML);
	КонецЕсли;	 
	
	Если Объект.СоздаватьИнструкциюMarkdown Тогда
		ОчиститьСодержимоеКаталога(Объект.КаталогOutputИнструкцияMarkdown);
	КонецЕсли;	 
	
	Если ВыполнятьСценарииАсинхронно Тогда
		ТекИД_СценарияВМассиве = -1;
		ПерейтиКВыполнениюСледующегоСценария();
	КонецЕсли;	 
	
КонецПроцедуры

&НаКлиенте
Процедура ВыполнитьСценарииФорма(Команда)
	
	ЭтаФорма.ТекущийЭлемент = Элементы.ГруппаЗапускТестов;
	СделатьПараметрыКорректными();
	
	ВыполнитьСценарии();
	
КонецПроцедуры

&НаКлиенте
Функция УбратьВсеЗапрещенныеСимволыИзИмениФайла(Стр)
	Стр = СтрЗаменить(Стр,"<","");
	Стр = СтрЗаменить(Стр,">","");
	Стр = СтрЗаменить(Стр,"""","");
	Стр = СтрЗаменить(Стр,"|","");
	Стр = СтрЗаменить(Стр,"*","");
	Стр = СтрЗаменить(Стр,"\","");
	Стр = СтрЗаменить(Стр,"/","");
	Стр = СтрЗаменить(Стр,":","");
	Стр = СтрЗаменить(Стр,"?","");
КонецФункции	


&НаКлиенте
Процедура СоздатьФайлHTMLИнструкции()
	Если НЕ Объект.СоздаватьИнструкциюHTML Тогда
		Возврат;
	КонецЕсли;	
	
	
	СтрокаОкончанияЗаголовка = 0;
	ЗаголовокФичи            = ПолучитьЗаголовокФичииИзЛогаИнструкции(ИмяФайлаЛогаИнструкцииHTML,СтрокаОкончанияЗаголовка);
	
	ТД = Новый ТекстовыйДокумент;
	ТД.Прочитать(ИмяФайлаЛогаИнструкцииHTML,КодировкаТекста.UTF8);
	
	МассивСценариев = Новый Массив;
	МассивШагов     = Неопределено;
	
	КолСтрок = ТД.КоличествоСтрок();
	Для Ккк = СтрокаОкончанияЗаголовка+1 По КолСтрок Цикл
		Стр = ТД.ПолучитьСтроку(Ккк);
		
		Если Стр = "НачалоСценария" Тогда
			ТекСтруктура = Новый Структура;
			МассивШагов  = Новый Массив;
			
			ТекСтруктура.Вставить("МассивШагов",МассивШагов);
			
			МассивСценариев.Добавить(ТекСтруктура);
			Продолжить;
		ИначеЕсли Стр = "НачалоШага" Тогда
			ТекСтруктура = Новый Структура;
			
			МассивШагов.Добавить(ТекСтруктура);
			Продолжить;
		КонецЕсли;	 
		
		Поз = Найти(Стр,"=");
		Если Поз = 0 Тогда
			ВызватьИсключение "Странный параметр в логе инструкции HTML: " + Стр;
		КонецЕсли;	 
		
		ИмяПараметра      = Лев(Стр,Поз-1);
		ЗначениеПараметра = Сред(Стр,Поз+1);
		
		ТекСтруктура.Вставить(ИмяПараметра,ЗначениеПараметра);
	КонецЦикла;
	
	КаталогОбъектов = Объект.КаталогOutputИнструкцияHTML;
	
	Страница = Новый ТекстовыйДокумент;
	Страница.ДобавитьСтроку("<html>");
	Страница.ДобавитьСтроку("<body>");
	
	
	Страница.ДобавитьСтроку("<h3><p  style=""font-size:40px"">");
	Для каждого Стр Из ЗаголовокФичи Цикл
		Страница.ДобавитьСтроку("<br>" + Стр);
	КонецЦикла;
	Страница.ДобавитьСтроку("</p></h3>");
	
	
	ИДСкриншота  = 0;
	Для каждого Сценарий Из МассивСценариев Цикл
		Страница.ДобавитьСтроку("<h1><p align=""center"" style=""font-size:35px"">" + Сценарий.ИмяСценария + "</p></h1>");
		
		
		ИмяФичи = Сценарий.ИмяФичи;
		УбратьВсеЗапрещенныеСимволыИзИмениФайла(ИмяФичи);
		ИмяФичи = СтрЗаменить(ИмяФичи," ","_");
		
		ИмяСценария = Сценарий.ИмяСценария;
		УбратьВсеЗапрещенныеСимволыИзИмениФайла(ИмяСценария);
		ИмяСценария = СтрЗаменить(ИмяСценария," ","_");
		
		
		
		КаталогФичи = ДополнитьСлешВПуть(КаталогОбъектов) + ИмяФичи;
		
		ФайлКаталогФичи = Новый Файл(КаталогФичи);
		Если НЕ ФайлСуществуетКомандаСистемы(ФайлКаталогФичи.ПолноеИмя) Тогда
		//Если НЕ ФайлКаталогФичи.Существует() Тогда
			СоздатьКаталогКомандаСистемы(КаталогФичи);
		КонецЕсли;  
		
		МассивШагов = Сценарий.МассивШагов;
		НомШага = 0;
		Для каждого Шаг Из МассивШагов Цикл
			ИДСкриншота = ИДСкриншота+1;
			НомШага = НомШага + 1;
			Страница.ДобавитьСтроку("");
			
			СтрокаШага = СтрЗаменить(Шаг.ИмяШага,"\n",Символы.ПС);
			МассивСтрок = РазложитьСтрокуВМассивПодстрок(СтрокаШага,Символы.ПС);
			Для Ккк = 0 По МассивСтрок.Количество()-1 Цикл
				Стр = МассивСтрок[Ккк];
				Если Ккк = 0 Тогда
					Страница.ДобавитьСтроку("<p align=""left"" style=""font-size:30px""><b>" + ПолучитьФорматированныйНомер(НомШага,3) + "</b>. " + Стр + "</p>");
				Иначе
					ЕстьВертЧерта = Ложь;
					Если Найти(Стр,"|") > 0 Тогда
						ЕстьВертЧерта = Истина;
					КонецЕсли;	 
					
					
					Если ЕстьВертЧерта Тогда
						Страница.ДобавитьСтроку("<p align=""left"" style=""font-size:30px""><pre><font size=""5"" face=""Lucida Console"">" + Стр + "</font></pre></p>");
					Иначе	
						Страница.ДобавитьСтроку("<p align=""left"" style=""font-size:30px"">" + Стр + "</p>");
					КонецЕсли;	 
				КонецЕсли;	 
				
			
			КонецЦикла;
			
			//Страница.ДобавитьСтроку("<p align=""left"" style=""font-size:30px""><b>" + ПолучитьФорматированныйНомер(НомШага,3) + "</b>. " + СтрЗаменить(Шаг.ИмяШага,"\n","<br>") + "</p>");
			
			ФайлСкриншота = Новый Файл(Шаг.Скриншот);
			
			
			НовоеИмяФайлаСкриншота = СтрЗаменить(ИмяФичи + "_" + ИДСкриншота + "_" + Лев(ИмяСценария,30) + "_" + ПолучитьФорматированныйНомер(НомШага,3) + ФайлСкриншота.Расширение," ","_");
			ИмяФайлаСкриншотаВКаталогеФичи = ФайлСкриншота.Путь + СтрЗаменить(ДополнитьСлешВПуть(ИмяФичи) + НовоеИмяФайлаСкриншота," ","_");
			ФайлСкриншота = Неопределено;
			
			ПроцедураПереместитьФайл(Шаг.Скриншот,ИмяФайлаСкриншотаВКаталогеФичи);
			//ПереместитьФайл(Шаг.Скриншот,ИмяФайлаСкриншотаВКаталогеФичи);
			
			СтрСкриншотаДляHTML = СтрЗаменить(ДополнитьСлешВПуть(ИмяФичи) + НовоеИмяФайлаСкриншота," ","_");
			
			Страница.ДобавитьСтроку("<img src=" + СтрЗаменить(СтрСкриншотаДляHTML,"\","/") + ">");
		КонецЦикла;
	КонецЦикла;
	
	
	Страница.ДобавитьСтроку("</body>");
	Страница.ДобавитьСтроку("/<html>");
	
	ИмяФайлаДляЗаписи = Объект.КаталогOutputИнструкцияHTML + "/Instr_" + ТекущаяФичаИнструкцииHTML + ".HTML";
	Сообщить("Записываю " + ИмяФайлаДляЗаписи);
	Страница.Записать(ИмяФайлаДляЗаписи);

	УдалитьФайлыКомандаСистемы(ИмяФайлаЛогаИнструкцииHTML);

КонецПроцедуры

&НаКлиенте
Функция ПолучитьЗаголовокФичииИзЛогаИнструкции(ИмяФайла,СтрокаОкончанияЗаголовка)
	Текст = Новый ЧтениеТекста;
	Текст.Открыть(ИмяФайла,"UTF-8");
	
	ЗаголовокФичи = Новый Массив;
	Ном = 0;
	Пока Истина Цикл
		Стр = Текст.ПрочитатьСтроку();
		Если Стр = Неопределено Тогда
			Прервать;
		КонецЕсли;	
		
		Ном = Ном + 1;
		
		Если Стр = "--окончание заголовка--" Тогда
			СтрокаОкончанияЗаголовка = Ном;
			Прервать;
		КонецЕсли;	 
		
		ЗаголовокФичи.Добавить(Стр);
	КонецЦикла;	
	
	Текст.Закрыть();
	
	Возврат ЗаголовокФичи;
КонецФункции	

&НаКлиенте
Процедура СоздатьФайлMarkdownИнструкции()
	Если НЕ Объект.СоздаватьИнструкциюMarkdown Тогда
		Возврат;
	КонецЕсли;	
	
	
	СтрокаОкончанияЗаголовка = 0;
	ЗаголовокФичи            = ПолучитьЗаголовокФичииИзЛогаИнструкции(ИмяФайлаЛогаИнструкцииMarkdown,СтрокаОкончанияЗаголовка);
	
	
	ТД = Новый ТекстовыйДокумент;
	ТД.Прочитать(ИмяФайлаЛогаИнструкцииMarkdown,КодировкаТекста.UTF8);
	
	МассивСценариев = Новый Массив;
	МассивШагов     = Неопределено;
	
	КолСтрок = ТД.КоличествоСтрок();
	Для Ккк = СтрокаОкончанияЗаголовка+1 По КолСтрок Цикл
		Стр = ТД.ПолучитьСтроку(Ккк);
		
		Если Стр = "НачалоСценария" Тогда
			ТекСтруктура = Новый Структура;
			МассивШагов  = Новый Массив;
			
			ТекСтруктура.Вставить("МассивШагов",МассивШагов);
			
			МассивСценариев.Добавить(ТекСтруктура);
			Продолжить;
		ИначеЕсли Стр = "НачалоШага" Тогда
			ТекСтруктура = Новый Структура;
			
			МассивШагов.Добавить(ТекСтруктура);
			Продолжить;
		КонецЕсли;	 
		
		Поз = Найти(Стр,"=");
		Если Поз = 0 Тогда
			ВызватьИсключение "Странный параметр в логе инструкции Markdown: " + Стр;
		КонецЕсли;	 
		
		ИмяПараметра      = Лев(Стр,Поз-1);
		ЗначениеПараметра = Сред(Стр,Поз+1);
		
		ТекСтруктура.Вставить(ИмяПараметра,ЗначениеПараметра);
	КонецЦикла;
	
	КаталогОбъектов = Объект.КаталогOutputИнструкцияMarkdown;
	
	
	ИмяФайлаДляЗаписи = Объект.КаталогOutputИнструкцияMarkdown + "/" + ТекущаяФичаИнструкцииMarkdown + ".MD";
	ЗТ = Новый ЗаписьТекста(ИмяФайлаДляЗаписи,"Windows-1251",,Ложь); 
	ЗТ.Закрыть();//убираю BOM, специально для ATOM
	
	
	
	Страница = Новый ЗаписьТекста(ИмяФайлаДляЗаписи,"UTF-8",,Истина); 
	//записываю заголовок
	Для каждого Стр Из ЗаголовокФичи Цикл
		Стр = СокрЛП(Стр);
		Если Найти(Стр,"Функционал:") > 0 Тогда
			Стр = СтрЗаменить(Стр,"Функционал:","**Функционал:**");
		ИначеЕсли НРег(Лев(Стр,3)) = "как" Тогда
			Стр =  "> **Как**" + Сред(Стр,4);
			
		ИначеЕсли НРег(Лев(Стр,4)) = "хочу" Тогда
			Стр =  "> **Хочу**" + Сред(Стр,5);
		ИначеЕсли НРег(Лев(Стр,6)) = "я хочу" Тогда
			Стр =  "> **Я хочу**" + Сред(Стр,7);
		ИначеЕсли НРег(Лев(Стр,5)) = "чтобы" Тогда
			Стр =  "> **Чтобы**" + Сред(Стр,6);
		Иначе
			Стр = " > " + Стр;
		КонецЕсли;	 
		
		Страница.ЗаписатьСтроку(Стр);
		Страница.ЗаписатьСтроку("");
	КонецЦикла;
	
	
	
	ИДСкриншота  = 0;
	ИДСценария   = 0;
	Для каждого Сценарий Из МассивСценариев Цикл
		ИДСценария = ИДСценария + 1;
		Если ИДСценария > 1 Тогда
			Страница.ЗаписатьСтроку("");
		КонецЕсли;	 
		Страница.ЗаписатьСтроку("");
		Страница.ЗаписатьСтроку("**Сценарий:** " + Сценарий.ИмяСценария);
		
		
		
		ИмяФичи = Сценарий.ИмяФичи;
		УбратьВсеЗапрещенныеСимволыИзИмениФайла(ИмяФичи);
		ИмяФичи = СтрЗаменить(ИмяФичи," ","_");
		
		ИмяСценария = Сценарий.ИмяСценария;
		УбратьВсеЗапрещенныеСимволыИзИмениФайла(ИмяСценария);
		ИмяСценария = СтрЗаменить(ИмяСценария," ","_");
		
		
		
		КаталогФичи = ДополнитьСлешВПуть(КаталогОбъектов) + ИмяФичи;
		
		ФайлКаталогФичи = Новый Файл(КаталогФичи);
		Если НЕ ФайлСуществуетКомандаСистемы(ФайлКаталогФичи.ПолноеИмя) Тогда
		//Если НЕ ФайлКаталогФичи.Существует() Тогда
			СоздатьКаталогКомандаСистемы(КаталогФичи);
		КонецЕсли;  
		
		МассивШагов = Сценарий.МассивШагов;
		НомШага = 0;
		Для каждого Шаг Из МассивШагов Цикл
			ИДСкриншота = ИДСкриншота+1;
			НомШага = НомШага + 1;
			Страница.ЗаписатьСтроку("");
			
			СтрокаШага = СтрЗаменить(Шаг.ИмяШага,"\n",Символы.ПС);
			МассивСтрок = РазложитьСтрокуВМассивПодстрок(СтрокаШага,Символы.ПС);
			Для Ккк = 0 По МассивСтрок.Количество()-1 Цикл
				Стр = МассивСтрок[Ккк];
				Если Ккк = 0 Тогда
					Страница.ЗаписатьСтроку("	" + ПолучитьФорматированныйНомер(НомШага,3) + ". " + Стр);
				Иначе
					ЕстьВертЧерта = Ложь;
					Если Найти(Стр,"|") > 0 Тогда
						ЕстьВертЧерта = Истина;
					КонецЕсли;	 
					
					
					Если ЕстьВертЧерта Тогда
						Страница.ЗаписатьСтроку("	" + Стр);
					Иначе	
						Страница.ЗаписатьСтроку("	" + Стр);
					КонецЕсли;	 
				КонецЕсли;	 
				
			
			КонецЦикла;
			
			//Страница.ДобавитьСтроку("<p align=""left"" style=""font-size:30px""><b>" + ПолучитьФорматированныйНомер(НомШага,3) + "</b>. " + СтрЗаменить(Шаг.ИмяШага,"\n","<br>") + "</p>");
			
			ФайлСкриншота = Новый Файл(Шаг.Скриншот);
			
			
			НовоеИмяФайлаСкриншота = СтрЗаменить(ИмяФичи + "_" + ИДСкриншота + "_" + Лев(ИмяСценария,30) + "_" + ПолучитьФорматированныйНомер(НомШага,3) + ФайлСкриншота.Расширение," ","_");
			ИмяФайлаСкриншотаВКаталогеФичи = ФайлСкриншота.Путь + СтрЗаменить(ДополнитьСлешВПуть(ИмяФичи) + НовоеИмяФайлаСкриншота," ","_");
			ФайлСкриншота = Неопределено;
			
			ПроцедураПереместитьФайл(Шаг.Скриншот,ИмяФайлаСкриншотаВКаталогеФичи);
			//ПереместитьФайл(Шаг.Скриншот,ИмяФайлаСкриншотаВКаталогеФичи);
			
			СтрСкриншотаДляMarkdown = СтрЗаменить(ДополнитьСлешВПуть(ИмяФичи) + НовоеИмяФайлаСкриншота," ","_");
			
			Страница.ЗаписатьСтроку("<img src=" + СтрЗаменить(СтрСкриншотаДляMarkdown,"\","/") + ">");
		КонецЦикла;
	КонецЦикла;
	
	
	
	Сообщить("Записываю " + ИмяФайлаДляЗаписи);
	//Страница.Записать(ИмяФайлаДляЗаписи);
	Страница.Закрыть();

	УдалитьФайлыКомандаСистемы(ИмяФайлаЛогаИнструкцииMarkdown);

КонецПроцедуры

&НаКлиенте
Процедура ПроцедураПереместитьФайл(Знач Стр1,Знач Стр2)
	ПереместитьФайлКомандаСистемы(Стр1,Стр2);
КонецПроцедуры

&НаКлиенте
Функция ПолучитьФорматированныйНомер(НомШага,КолСимволов)
	Стр = Строка(НомШага);
	Стр = СтрЗаменить(Стр,Символы.НПП,"");
	
	Пока СтрДлина(Стр) < КолСимволов Цикл
		Стр = "0" + Стр;
	КонецЦикла; 
	
	Возврат Стр; 
КонецФункции	

//портирован блок ассертов из проекта xUnitFor1C (https://github.com/xDrivenDevelopment/xUnitFor1C)
//был взят релиз 3.0.0.3
//{ МЕТОДЫ ДЛЯ ПРОВЕРКИ ЗНАЧЕНИЙ (assertions). 

&НаКлиенте
Функция ФорматДСО(ДопСообщениеОшибки)
	Если ДопСообщениеОшибки = "" Тогда
		Возврат "";
	КонецЕсли;
	
	Возврат Символы.ПС + ДопСообщениеОшибки;
КонецФункции

&НаКлиенте
Процедура ВызватьОшибкуПроверки(СообщениеОшибки)
	
	Префикс = "[" + СтатусыРезультатаТестирования.ОшибкаПроверки + "]";
	ВызватьИсключение Префикс + " " + СообщениеОшибки;
	
КонецПроцедуры

&НаКлиенте
Процедура Проверить(_Истина, ДопСообщениеОшибки = "") Экспорт
	Если Не _Истина Тогда
		СообщениеОшибки = "Переданный параметр ("+Формат(_Истина, "БЛ=ложь; БИ=истина")+") не является Истиной, а хотели, чтобы являлся." + ФорматДСО(ДопСообщениеОшибки);
		ВызватьОшибкуПроверки(СообщениеОшибки);
	КонецЕсли;
КонецПроцедуры

&НаКлиенте
Процедура ПроверитьИстину(_Истина, ДопСообщениеОшибки = "") Экспорт
	Проверить(_Истина, ДопСообщениеОшибки);
КонецПроцедуры

&НаКлиенте
Процедура ПроверитьЛожь(_Ложь, ДопСообщениеОшибки = "") Экспорт
	Если _Ложь Тогда
		СообщениеОшибки = "Переданный параметр ("+Формат(_Ложь, "БЛ=ложь; БИ=истина")+") не является Ложью, а хотели, чтобы являлся." + ФорматДСО(ДопСообщениеОшибки);
		ВызватьОшибкуПроверки(СообщениеОшибки);
	КонецЕсли;
КонецПроцедуры

&НаКлиенте
Процедура ПроверитьДату(_Дата, _Период, ДопСообщениеОшибки = "") Экспорт
	Если _Дата < _Период.ДатаНачала или _Дата > _Период.ДатаОкончания Тогда
		представление = ПредставлениеПериода(_Период.ДатаНачала, _Период.ДатаОкончания, "ФП = Истина");
		СообщениеОшибки = "Переданный параметр ("+Формат(_Дата, "ДФ='dd.MM.yyyy HH:mm:ss'")+") не входит в период "+представление+", а хотели, чтобы являлся." + ФорматДСО(ДопСообщениеОшибки);
		ВызватьОшибкуПроверки(СообщениеОшибки);
	КонецЕсли;
КонецПроцедуры

&НаКлиенте
Процедура ПроверитьРавенствоДатСТочностью2Секунды(_Дата, _Дата2, ДопСообщениеОшибки = "") Экспорт
	Если _Дата < _Дата2-2 или _Дата > _Дата2+2 Тогда
		СообщениеОшибки = "Переданная дата ("+Формат(_Дата, "ДФ='dd.MM.yyyy HH:mm:ss'")+") не равна дате ("+Формат(_Дата2, "ДФ='dd.MM.yyyy HH:mm:ss'")+") с точностью до 2-х секунд, а хотели, чтобы они равнялись." + ФорматДСО(ДопСообщениеОшибки);
		ВызватьОшибкуПроверки(СообщениеОшибки);
	КонецЕсли;
КонецПроцедуры

&НаКлиенте
Процедура ПроверитьРавенство(_1, _2, ДопСообщениеОшибки = "") Экспорт
	Если _1 <> _2 Тогда
		СообщениеОшибки = "Сравниваемые значения ("+_1+"; "+_2+") не равны, а хотели, чтобы были равны." + ФорматДСО(ДопСообщениеОшибки);
		ВызватьОшибкуПроверки(СообщениеОшибки);
	КонецЕсли;
КонецПроцедуры

&НаКлиенте
Процедура ПроверитьНеРавенство(_1, _2, ДопСообщениеОшибки = "") Экспорт
	Если _1 = _2 Тогда
		СообщениеОшибки = "Сравниваемые значения ("+_1+"; "+_2+") равны, а хотели, чтобы были не равны." + ФорматДСО(ДопСообщениеОшибки);
		ВызватьОшибкуПроверки(СообщениеОшибки);
	КонецЕсли;
КонецПроцедуры

&НаКлиенте
Процедура ПроверитьБольше(_Больше, _Меньше, ДопСообщениеОшибки = "") Экспорт
	Если _Больше <= _Меньше Тогда
		СообщениеОшибки = "Первый параметр ("+_Больше+") меньше или равен второму ("+_Меньше+") а хотели, чтобы был больше." + ФорматДСО(ДопСообщениеОшибки);
		ВызватьОшибкуПроверки(СообщениеОшибки);
	КонецЕсли;
КонецПроцедуры

&НаКлиенте
Процедура ПроверитьБольшеИлиРавно(_Больше, _Меньше, ДопСообщениеОшибки = "") Экспорт
	Если _Больше < _Меньше Тогда
		СообщениеОшибки = "Первый параметр ("+_Больше+") меньше второго ("+_Меньше+") а хотели, чтобы был больше или равен." + ФорматДСО(ДопСообщениеОшибки);
		ВызватьОшибкуПроверки(СообщениеОшибки);
	КонецЕсли;
КонецПроцедуры

&НаКлиенте
Процедура ПроверитьМеньше(проверяемоеЗначение1, проверяемоеЗначение2, СообщениеОбОшибке = "") Экспорт
	Если проверяемоеЗначение1 >= проверяемоеЗначение2 Тогда
		СообщениеОшибки = "Значение <"+проверяемоеЗначение1+"> больше или равно, чем <"+проверяемоеЗначение2+">, а ожидалось меньше"+
		ФорматДСО(СообщениеОбОшибке);
		ВызватьОшибкуПроверки(СообщениеОшибки)
	КонецЕсли;
КонецПроцедуры

&НаКлиенте
Процедура ПроверитьМеньшеИлиРавно(проверяемоеЗначение1, проверяемоеЗначение2, СообщениеОбОшибке = "") Экспорт
	Если проверяемоеЗначение1 > проверяемоеЗначение2 Тогда
		СообщениеОшибки = "Значение <"+проверяемоеЗначение1+"> больше, чем <"+проверяемоеЗначение2+">, а ожидалось меньше или равно"+
		ФорматДСО(СообщениеОбОшибке);
		ВызватьОшибкуПроверки(СообщениеОшибки)
	КонецЕсли; 
КонецПроцедуры

&НаКлиенте
Процедура ПроверитьВыполнилось(Знач СтрокаАлгоритм, ПараметрыИлиДопСообщениеОшибки = Неопределено, Знач ДопСообщениеОшибки = "") Экспорт
	Перем Параметры;
	
	Если ТипЗнч(ПараметрыИлиДопСообщениеОшибки) = Тип("Строка") Тогда
		ДопСообщениеОшибки = ПараметрыИлиДопСообщениеОшибки;
	Иначе
		Параметры = ПараметрыИлиДопСообщениеОшибки;
	КонецЕсли;
	Попытка
		Выполнить(СтрокаАлгоритм);
	Исключение
		ПолученноеОписаниеОшибки = ПодробноеПредставлениеОшибки(ИнформацияОбОшибке());
		СообщениеОшибки = "Хотели, чтобы алгоритм """+СтрокаАлгоритм+""" выполнился, а он упал с ошибкой """+ПолученноеОписаниеОшибки+"""." + ФорматДСО(ДопСообщениеОшибки);
		ВызватьОшибкуПроверки(СообщениеОшибки);
	КонецПопытки;
	
КонецПроцедуры

&НаКлиенте
Процедура ПроверитьМетодВыполнился(Объект, Знач ИмяМетода, ПараметрыИлиДопСообщениеОшибки = Неопределено, Знач ДопСообщениеОшибки = "") Экспорт
	Перем Параметры;
	
	Если ТипЗнч(ПараметрыИлиДопСообщениеОшибки) = Тип("Строка") Тогда
		ДопСообщениеОшибки = ПараметрыИлиДопСообщениеОшибки;
	Иначе
		Параметры = ПараметрыИлиДопСообщениеОшибки;
		Если Параметры <> Неопределено Тогда
			ТипПараметра = ТипЗнч(Параметры);
			Если ТипПараметра <> Тип("Массив") Тогда
				ВызватьИсключение ("Ожидали, что вторым параметром будет передан массив параметров для метода <"+ИмяМетода+">, а получили другой объект с типом <"+ТипПараметра+">");
			КонецЕсли;
		КонецЕсли;
	КонецЕсли;
	
	ПараметрыСтрока = ПараметрыСтрокой(Параметры);
	
	СтрокаВыполнения = "Объект." + ИмяМетода + "(" + ПараметрыСтрока + ")";
	
	Попытка
		Выполнить(СтрокаВыполнения);
	Исключение
		ПолученноеОписаниеОшибки = ПодробноеПредставлениеОшибки(ИнформацияОбОшибке());
		СообщениеОшибки = "Хотели, чтобы код """+СтрокаВыполнения+""" выполнился, а он упал с ошибкой """+ПолученноеОписаниеОшибки+"""." + ФорматДСО(ДопСообщениеОшибки);
		ВызватьОшибкуПроверки(СообщениеОшибки);
	КонецПопытки;
	
КонецПроцедуры

&НаКлиентеНаСервереБезКонтекста
Функция ПараметрыСтрокой(Параметры, ИмяПеременной = "Параметры")
	
	ПараметрыСтрока = "";
	Если Параметры <> Неопределено Тогда
		Если ТипЗнч(Параметры) = Тип("Массив") Тогда
			Для Индекс = 0 По Параметры.ВГраница() Цикл 
				ПараметрыСтрока = ПараметрыСтрока + ", " + ИмяПеременной + "[" + Формат(Индекс, "ЧН=0; ЧГ=0") + "]";
			КонецЦикла;
			ПараметрыСтрока = Сред(ПараметрыСтрока, 3);
		Иначе
			ПараметрыСтрока = ИмяПеременной;
		КонецЕсли;
	КонецЕсли;
	
	Возврат ПараметрыСтрока;
	
КонецФункции

&НаКлиенте
Процедура ПроверитьНеВыполнилось(Знач СтрокаАлгоритм, ПараметрыИлиОжидаемоеОписаниеОшибки, Знач ОжидаемоеОписаниеОшибкиИлиДопСообщениеОшибки = "", Знач ДопСообщениеОшибки = "") Экспорт
	Перем Параметры, ОжидаемоеОписаниеОшибки; 
	Если ТипЗнч(ПараметрыИлиОжидаемоеОписаниеОшибки) = Тип("Строка") Тогда
		ОжидаемоеОписаниеОшибки = ПараметрыИлиОжидаемоеОписаниеОшибки;
		ДопСообщениеОшибки = ОжидаемоеОписаниеОшибкиИлиДопСообщениеОшибки;
	Иначе
		Параметры = ПараметрыИлиОжидаемоеОписаниеОшибки;
		ОжидаемоеОписаниеОшибки = ОжидаемоеОписаниеОшибкиИлиДопСообщениеОшибки;
	КонецЕсли;
	Попытка
		Выполнить(СтрокаАлгоритм);
	Исключение
		ПолученноеОписаниеОшибки = ПодробноеПредставлениеОшибки(ИнформацияОбОшибке());
		Если Найти(ПолученноеОписаниеОшибки, ОжидаемоеОписаниеОшибки) = 0 Тогда
			ВызватьОшибкуПроверки("Хотели, чтобы алгоритм """+СтрокаАлгоритм+""" упал с сообщением об ошибке """+ОжидаемоеОписаниеОшибки+""", а он упал с сообщением """+ПолученноеОписаниеОшибки+"""." + ФорматДСО(ДопСообщениеОшибки));
		КонецЕсли;
		Возврат;
	КонецПопытки;
	
	ВызватьОшибкуПроверки("Хотели, чтобы алгоритм """+СтрокаАлгоритм+""" упал, а он выполнился" + ФорматДСО(ДопСообщениеОшибки));
	
КонецПроцедуры

&НаКлиенте
Процедура ПроверитьМетодНеВыполнился(Объект, ИмяМетода, ПараметрыИлиОжидаемоеОписаниеОшибки, Знач ОжидаемоеОписаниеОшибкиИлиДопСообщениеОшибки = "", Знач ДопСообщениеОшибки = "") Экспорт
	Перем Параметры, ОжидаемоеОписаниеОшибки; 
	
	Если ТипЗнч(ПараметрыИлиОжидаемоеОписаниеОшибки) = Тип("Строка") Тогда
		ОжидаемоеОписаниеОшибки = ПараметрыИлиОжидаемоеОписаниеОшибки;
		ДопСообщениеОшибки = ОжидаемоеОписаниеОшибкиИлиДопСообщениеОшибки;
	Иначе
		Параметры = ПараметрыИлиОжидаемоеОписаниеОшибки;
		Если Параметры <> Неопределено Тогда
			ТипПараметра = ТипЗнч(Параметры);
			Если ТипПараметра <> Тип("Массив") Тогда
				ВызватьИсключение ("Ожидали, что третьим параметром будет передан массив параметров для метода <"+ИмяМетода+">, а получили другой объект с типом <"+ТипПараметра+">");
			КонецЕсли;
		КонецЕсли;
		ОжидаемоеОписаниеОшибки = ОжидаемоеОписаниеОшибкиИлиДопСообщениеОшибки;
	КонецЕсли;
	
	ПараметрыСтрока = ПараметрыСтрокой(Параметры);
	
	СтрокаВыполнения = "Объект." + ИмяМетода + "(" + ПараметрыСтрока + ")";
	
	Попытка
		Выполнить(СтрокаВыполнения);
	Исключение
		ПолученноеОписаниеОшибки = ПодробноеПредставлениеОшибки(ИнформацияОбОшибке());
		Если Найти(ПолученноеОписаниеОшибки, ОжидаемоеОписаниеОшибки) = 0 Тогда
			ВызватьОшибкуПроверки("Хотели, чтобы код """+СтрокаВыполнения+""" упал с сообщением об ошибке """+ОжидаемоеОписаниеОшибки+""", а он упал с сообщением """+ПолученноеОписаниеОшибки+"""." + ФорматДСО(ДопСообщениеОшибки));
		КонецЕсли;
		Возврат;
	КонецПопытки;
	
	ВызватьОшибкуПроверки("Хотели, чтобы код """+СтрокаВыполнения+""" упал, а он выполнился" + ФорматДСО(ДопСообщениеОшибки));
	
КонецПроцедуры

// проверка идет через ЗначениеЗаполнено, но мутабельные значение всегда считаем заполненными
&НаКлиенте
Процедура ПроверитьЗаполненность(ПроверяемоеЗначение, ДопСообщениеОшибки = "") Экспорт
	Попытка
		фЗаполнено = ЗначениеЗаполнено(ПроверяемоеЗначение);
	Исключение
		Возврат;
	КонецПопытки;
	Если НЕ фЗаполнено Тогда
		ВызватьОшибкуПроверки("Значение ("+ПроверяемоеЗначение+") не заполнено, а ожидалась заполненность" + ФорматДСО(ДопСообщениеОшибки));
	КонецЕсли; 
КонецПроцедуры

&НаКлиенте
Процедура ПроверитьНеЗаполненность(ПроверяемоеЗначение, ДопСообщениеОшибки = "") Экспорт
	СообщениеОшибки = "Значение ("+ПроверяемоеЗначение+") заполнено, а ожидалась незаполненность" + ФорматДСО(ДопСообщениеОшибки);
	Попытка
		фЗаполнено = ЗначениеЗаполнено(ПроверяемоеЗначение);
	Исключение
		ВызватьОшибкуПроверки(СообщениеОшибки);
	КонецПопытки;
	Если фЗаполнено Тогда
		ВызватьОшибкуПроверки(СообщениеОшибки);
	КонецЕсли; 
КонецПроцедуры

&НаКлиенте
Процедура ПроверитьТип(значение, ТипИлиИмяТипа, ДопСообщениеОшибки = "") Экспорт
	Если ТипЗнч(ТипИлиИмяТипа) = Тип("Строка") Тогда
		искомыйТип = Тип(ТипИлиИмяТипа);
	ИначеЕсли ТипЗнч(ТипИлиИмяТипа) = Тип("Тип") Тогда
		искомыйТип = ТипИлиИмяТипа;
	Иначе
		ВызватьИсключение ("ПроверитьТип: Тип значения параметра ТипИлиИмяТипа должен быть <Тип> или <Строка>, а получили <"+ ТипЗнч(ТипИлиИмяТипа) + ">" + ФорматДСО(ДопСообщениеОшибки));
	КонецЕсли;
	Если ТипЗнч(значение) <> искомыйТип Тогда
		ВызватьОшибкуПроверки("Типом значения <"+значение+"> является <"+ТипЗнч(значение)+">, а ожидался тип <"+ТипИлиИмяТипа+">."+ФорматДСО(ДопСообщениеОшибки));
	КонецЕсли;
КонецПроцедуры

&НаКлиенте
Процедура ПроверитьВхождение(строка, подстрокаПоиска, ДопСообщениеОшибки = "") Экспорт
	Если Найти(строка, подстрокаПоиска) = 0 Тогда
		ПредставлениеСтроки = "<"+строка+">";
		Если СтрДлина(строка) > 20 Тогда
			ПредставлениеСтроки = ПредставлениеСтроки + Символы.ПС;
		КонецЕсли;
		ПредставлениеПодСтроки = "<"+подстрокаПоиска+">";
		Если СтрДлина(подстрокаПоиска) > 20 Тогда
			ПредставлениеПодСтроки = ПредставлениеПодСтроки + Символы.ПС;
		КонецЕсли;
		СообщениеОшибки = "Искали в "+ПредставлениеСтроки+" подстроку "+ПредставлениеПодСтроки+", но не нашли." + ФорматДСО(ДопСообщениеОшибки);
		ВызватьОшибкуПроверки(СообщениеОшибки);
	КонецЕсли;
КонецПроцедуры

//Коллекция - Массив, Структура, Соответствие, ФиксированныйМассив, ФиксированнаяСтруктура, ФиксированноеСоответствие, СписокЗначений
&НаКлиенте
Процедура ПроверитьВхождениеВКоллекцию(Элемент, Коллекция, ДопСообщениеОшибки = "") Экспорт
	Нашли = Неопределено;
	ТипКоллекции = ТипЗнч(Коллекция);
	Если ТипКоллекции = Тип("Массив") или ТипКоллекции = Тип("ФиксированныйМассив") Тогда
		Нашли = Коллекция.Найти(Элемент) <> Неопределено;
	ИначеЕсли ТипКоллекции = Тип("Структура") или ТипКоллекции = Тип("Соответствие") 
		или ТипКоллекции = Тип("ФиксированнаяСтруктура") или ТипКоллекции = Тип("ФиксированноеСоответствие") Тогда
		Для каждого КлючЗначение Из Коллекция Цикл
			Нашли = КлючЗначение.Значение = Элемент;
			Если Нашли Тогда
				Прервать;
			КонецЕсли;
		КонецЦикла;
	ИначеЕсли ТипКоллекции = Тип("СписокЗначений") Тогда
		Нашли = Коллекция.НайтиПоЗначению(Элемент) <> Неопределено;
	КонецЕсли;
	Если Нашли = Неопределено Тогда
		СообщениеОшибки = "Утверждение ""ПроверитьВхождениеВКоллекцию"" не умеет работать с типом коллекции <"+ТипКоллекции+">." + ФорматДСО(ДопСообщениеОшибки);
		ВызватьИсключение СообщениеОшибки;
	КонецЕсли;
	Если Не Нашли Тогда
		СообщениеОшибки = "Не нашли элемент <"+Элемент+"> в коллекции, а хотели, чтобы он был в коллекции." + ФорматДСО(ДопСообщениеОшибки);
		ВызватьОшибкуПроверки(СообщениеОшибки);
	КонецЕсли;
КонецПроцедуры

&НаКлиенте
Процедура ПроверитьВалидностьЗапросаСКД(ТекстЗапроса, ДопСообщениеОшибки = "") Экспорт
	ПроверитьВалидностьЗапросаСКДНаСервере(ТекстЗапроса, ДопСообщениеОшибки);
КонецПроцедуры

// Только для внутреннего использования
&НаСервере
Процедура ПроверитьВалидностьЗапросаСКДНаСервере(ТекстЗапроса, ДопСообщениеОшибки = "")
	Объект().ПроверитьВалидностьЗапросаСКД(ТекстЗапроса, ДопСообщениеОшибки);
КонецПроцедуры

&НаКлиенте
Процедура ПроверитьРавенствоТабличныхДокументовТолькоПоЗначениям(ТабДок1, ТабДок2, УчитыватьТолькоВидимыеКолонкиИлиДопСообщениеОшибки = Ложь, УчитыватьТолькоВидимыеСтрокиИлиДопСообщениеОшибки = Ложь, Знач ДопСообщениеОшибки = "") Экспорт
	ПроверитьРавенствоТабличныхДокументовТолькоПоЗначениямСервер(ТабДок1, ТабДок2, УчитыватьТолькоВидимыеКолонкиИлиДопСообщениеОшибки, УчитыватьТолькоВидимыеСтрокиИлиДопСообщениеОшибки, ДопСообщениеОшибки);
КонецПроцедуры

&НаСервере
Процедура ПроверитьРавенствоТабличныхДокументовТолькоПоЗначениямСервер(ТабДок1, ТабДок2, УчитыватьТолькоВидимыеКолонкиИлиДопСообщениеОшибки = Ложь, УчитыватьТолькоВидимыеСтрокиИлиДопСообщениеОшибки = Ложь, Знач ДопСообщениеОшибки = "") Экспорт
	Объект().ПроверитьРавенствоТабличныхДокументовТолькоПоЗначениям(ТабДок1, ТабДок2, УчитыватьТолькоВидимыеКолонкиИлиДопСообщениеОшибки, УчитыватьТолькоВидимыеСтрокиИлиДопСообщениеОшибки, ДопСообщениеОшибки);
КонецПроцедуры

&НаСервере
Функция Объект() Экспорт
	ОбъектНаСервере = РеквизитФормыВЗначение("Объект");
	Возврат ОбъектНаСервере;
КонецФункции

&НаСервере
Процедура ДобавитьШагиВМассив(ДеревоСтроки,Шаги)
	Для каждого СтрДеревоСтроки Из ДеревоСтроки Цикл
		Если СтрДеревоСтроки.Примеры = Истина Тогда
			//эти сценарии уже учтены
			Продолжить;
		КонецЕсли; 
		
		Если СтрДеревоСтроки.Шаг = Истина Тогда
			СтруктураШага = Новый Структура;
			СтруктураШага.Вставить("Имя",СтрДеревоСтроки.Имя);
			СтруктураШага.Вставить("ИмяШагаБезКлючевогоСлова",СтрДеревоСтроки.ИмяШагаБезКлючевогоСлова);
			СтруктураШага.Вставить("АдресСнипета",СтрДеревоСтроки.АдресСнипета);
			СтруктураШага.Вставить("ШагСПараметрамиВТаблице",СтрДеревоСтроки.ШагСПараметрамиВТаблице);
			Шаги.Добавить(СтруктураШага);
		КонецЕсли;	 
		ДобавитьШагиВМассив(СтрДеревоСтроки.Строки,Шаги);
	КонецЦикла	
КонецПроцедуры

&НаСервере
Процедура ДобавитьИменаФайловФичИзДереваВМассив(ДеревоСтроки,МассивФич,МассивШагов)
	Для каждого СтрДеревоСтроки Из ДеревоСтроки Цикл
		Если СтрДеревоСтроки.Фича = Истина Тогда
			МассивФич.Добавить(СтрДеревоСтроки.ПолныйПуть);
			Шаги = Новый Массив;
			ДобавитьШагиВМассив(СтрДеревоСтроки.Строки,Шаги);
			МассивШагов.Добавить(Шаги);
		КонецЕсли;	 
		ДобавитьИменаФайловФичИзДереваВМассив(СтрДеревоСтроки.Строки,МассивФич,МассивШагов);
	КонецЦикла;
КонецПроцедуры

&НаСервере
Процедура ПолучитьСписокФичПоДеревуИСоздатьEPFПоМассивуФич(СтруктураПараметров,МассивФич,МассивШагов)
	ОбъектСервер = РеквизитФормыВЗначение("Объект");
	Дерево = ОбъектСервер.ДеревоТестов;
	
	
	ДобавитьИменаФайловФичИзДереваВМассив(Дерево.Строки,МассивФич,МассивШагов);
	
	
	//СоздатьEPFПоМассивуФич(СтруктураПараметров);
	
	
	//ВременноеИмяФайла = ПолучитьИмяВременногоФайла("epf");
	//ДвДанныеvbFeatureReader.Записать(ВременноеИмяФайла);
	//FeatureReader = ВнешниеОбработки.Создать(ВременноеИмяФайла,Ложь);
	
	СтруктураПараметров.Вставить("КонтекстVanessaBehavoir",ОбъектСервер);
	
	
	//СоздатьEPFПоМассивуФич(СтруктураПараметров);
	
	//FeatureReader.СоздатьEPFПоМассивуФич(СтруктураПараметров);
	
	//УдалитьФайлы(ВременноеИмяФайла);
	
	СтруктураПараметров.КонтекстVanessaBehavoir = "";
	
	//ЗначениеВРеквизитФормы(ОбъектСервер,"Объект");
КонецПроцедуры

&НаКлиенте
Процедура ВыполнитьКомандуОС(Стр)
	КомандаСистемы(Стр);
КонецПроцедуры

&НаКлиенте
Функция УстановленПитон()
	ИмяФайлаЛога = ПолучитьИмяВременногоФайла("txt");
	Стр = "python --version > """ + ИмяФайлаЛога + """ 2>&1";
	
	ВыполнитьКомандуОС(Стр);
	
	Текст = Новый ЧтениеТекста;
	Текст.Открыть(ИмяФайлаЛога,"UTF-8");
	
	СтрокаВозврата = Неопределено;
	
	КолСтрокСчитано = 0;
	Пока Истина Цикл
		Стр = Текст.ПрочитатьСтроку();
		//Сообщить("" + Стр);
		
		
		Если Стр = Неопределено Тогда
			Прервать;
		КонецЕсли;
		КолСтрокСчитано = КолСтрокСчитано + 1;
		
		Если Найти(НРег(Стр),"""") > 0 Тогда
			//значит там сообщение про неизвестую команду системы
			Текст.Закрыть();
			Возврат Ложь;
		КонецЕсли;	 
		
	КонецЦикла;	
	Текст.Закрыть();
	
	Если КолСтрокСчитано = 0 Тогда
		Возврат Ложь;
	КонецЕсли;	 
	
	Возврат Истина;
КонецФункции	

&НаКлиенте
Функция ВПеременнойPathЕстьUnpackV8_exe()
	ИмяФайлаЛога = ПолучитьИмяВременногоФайла("txt");
	Стр = "v8unpack > " + ИмяФайлаЛога;
	
	ВыполнитьКомандуОС(Стр);
	
	Текст = Новый ЧтениеТекста;
	Текст.Открыть(ИмяФайлаЛога,"UTF-8");
	
	СтрокаВозврата = Неопределено;
	
	Пока Истина Цикл
		Стр = Текст.ПрочитатьСтроку();
		Если Стр = Неопределено Тогда
			Прервать;
		КонецЕсли;	 
		//"V8Upack Version 2.00 Copyright (c) 2008 Denis Demidov 2008-03-30"
		Если Найти(НРег(Стр),"version") > 0 Тогда
			Текст.Закрыть();
			Возврат Истина;
		КонецЕсли;	 
		
	КонецЦикла;	
	Текст.Закрыть();
	
	Возврат Ложь;
КонецФункции

&НаКлиенте
Процедура ЗаписатьФайлВерсииИсходников(ИмяФайлаВерсииИсходников,ИмяФайлаОригинала)
	Возврат;
	
	
	ФайлВерсии = Новый Файл(ИмяФайлаВерсииИсходников);
	Если ФайлВерсии.Существует() Тогда
		УдалитьФайлы(ФайлВерсии.ПолноеИмя);
	КонецЕсли;	 
	
	Файл   = Новый Файл(ИмяФайлаОригинала);
	Версия = Строка(Файл.ПолучитьВремяИзменения());
	
	ЗТ = Новый ЗаписьТекста(ИмяФайлаВерсииИсходников,"UTF-8",,Истина); 
	ЗТ.ЗаписатьСтроку("Версия="+Версия); 
	
	ЗТ.Закрыть();
	
КонецПроцедуры

&НаКлиенте
Функция РаспаковатьEPF(СтруктураОписанияEpf)
	ИмяФайла = СтруктураОписанияEpf.ИмяФайлаEPF;
	
	ГенерироватьУФ      = Объект.ГенерироватьУФ;
	КаталогИнструментов = Объект.КаталогИнструментов;
	ЭтоУФ               = Истина;
	Если ЭтоLinux Тогда 
		Возврат Неопределено;
	КонецЕсли;
	
	Попытка
		
		Файл = Новый Файл(ИмяФайла);
		ВременноеИмяФайла = ПолучитьИмяВременногоФайла("epf");
		КопироватьФайлКомандаСистемы(ИмяФайла,ВременноеИмяФайла);
		
		ВременныйФайл = Новый Файл(ВременноеИмяФайла);
		
		ИмяКаталогаДляИсходников = ДополнитьСлешВПуть(ВременныйФайл.Путь) + "Src";
		ИмяФайлаВерсииИсходников = ДополнитьСлешВПуть(ВременныйФайл.Путь) + ДополнитьСлешВПуть("Src") + ДополнитьСлешВПуть(ВременныйФайл.ИмяБезРасширения) + "SrcVersion.vb";
		
		Если ГенерироватьУФ Тогда
			ПутьКФайлуМодуля = ДополнитьСлешВПуть(ИмяКаталогаДляИсходников) + ВременныйФайл.ИмяБезРасширения + "/Form/Форма/Форма.txt";
		Иначе	
			ПутьКФайлуМодуля = ДополнитьСлешВПуть(ИмяКаталогаДляИсходников) + ВременныйФайл.ИмяБезРасширения + "/ObjectModule.txt";
		КонецЕсли;	 
		
		УдалитьКаталогКомандаСистемы(ДополнитьСлешВПуть(ИмяКаталогаДляИсходников) + ВременныйФайл.ИмяБезРасширения);
		ФайлКаталогSrc = Новый Файл(ИмяКаталогаДляИсходников);
		Если ФайлСуществуетКомандаСистемы(ФайлКаталогSrc.ПолноеИмя) Тогда
			СоздатьКаталогКомандаСистемы(ИмяКаталогаДляИсходников);
		КонецЕсли;	 
		
		СтрокаЗапуска = ?(ЭтоLinux = Истина,  "python3", "python");
		
		СтрокаРазборкиEpf = СтрокаЗапуска + " " + ДополнитьСлешВПуть(КаталогИнструментов) + "vendor/precommit1c/pyv8unpack.py  """ +  ВременноеИмяФайла + """ """ + ИмяКаталогаДляИсходников + """";
		СделатьСообщение("Делаю распаковку " + Файл.ПолноеИмя);
		Отладка("Строка распаковки: " + СтрокаРазборкиEpf);
		
		#Если Клиент Тогда
		КомандаСистемы(СтрокаРазборкиEpf,КаталогИнструментов);
		#КонецЕсли
		
		Файл = Новый Файл(ПутьКФайлуМодуля);
		Если НЕ ФайлСуществуетКомандаСистемы(ВременныйФайл.ПолноеИмя) Тогда
			СделатьСообщение("Не найден файл после распаковки: " + ПутьКФайлуМодуля);
			Если ЭтоУФ Тогда
				СделатьСообщение("Возможно это обработка для обычных форм, а не для управляемых форм.");
			Иначе	
				СделатьСообщение("Возможно это обработка для управляемых форм, а не для обычных форм.");
			КонецЕсли;	 
			Возврат Неопределено;
		КонецЕсли;	 
		
		
		СтруктураОписанияEpf.КаталогИсходников = ИмяКаталогаДляИсходников + "\" + ВременныйФайл.ИмяБезРасширения;
		ЗаписатьФайлВерсииИсходников(ИмяФайлаВерсииИсходников,ИмяФайла);
		
		Возврат ПутьКФайлуМодуля;
		
	Исключение
		СделатьСообщение("Не смог распаковать " + ИмяФайла);
		СделатьСообщение(ОписаниеОшибки());
		Возврат Неопределено;
	КонецПопытки;
КонецФункции

&НаКлиенте
Функция СоздатьПустуюСтруктуруEpf()
	Стр = Новый Структура;
	Стр.Вставить("ИмяФичи","");
	Стр.Вставить("ИмяФайлаEpf","");
	Стр.Вставить("ВременноеИмяМодуля","");
	Стр.Вставить("ТелоМодуля","");//таблица значений
	Стр.Вставить("ИмяМодуляEpf","");
	Стр.Вставить("КаталогИсходников","");
	Стр.Вставить("ФайлEpfПересоздавался",Ложь);
	
	Возврат Стр;
КонецФункции

&НаСервере
Функция ЗагрузитьТелоМодуляВТаблицуЗначенийСервер(ДвоичныеДанные,ШагСтрокДляМодуля)
	ПутьКФайлу = ПолучитьИмяВременногоФайла("txt");
	
	ДвоичныеДанные.Записать(ПутьКФайлу);
	
	Тзн = Новый ТаблицаЗначений;
	Тзн.Колонки.Добавить("НомСтр");
	Тзн.Колонки.Добавить("Стр");
	
	НомСтр = 0;
	ПромФайл = Новый Файл(ПутьКФайлу);
	Если Не ПромФайл.Существует() Тогда
		СтрОшибки = "Файл """ + ПутьКФайлу + """ не существует!";
		Сообщить(СтрОшибки);
		ВызватьИсключение СтрОшибки;
	КонецЕсли; 
	
	Текст = Новый ЧтениеТекста;
	Текст.Открыть(ПутьКФайлу,"UTF-8");
	
	Пока Истина Цикл
		Стр = Текст.ПрочитатьСтроку();
		Если Стр = Неопределено Тогда
			Прервать;
		КонецЕсли;	 
		
		НомСтр = НомСтр + ШагСтрокДляМодуля;
		
		СтрТзн        = Тзн.Добавить();
		СтрТзн.НомСтр = НомСтр;
		СтрТзн.Стр    = Стр;
	КонецЦикла;	
	
	Текст.Закрыть();
	
	Возврат ЗначениеВСтрокуВнутр(Тзн);
КонецФункции	

&НаКлиенте
Функция ЗагрузитьТелоМодуляВТаблицуЗначений(ПутьКФайлу)
	//ВызватьИсключение "НЕ реализовано ЗагрузитьТелоМодуляВТаблицуЗначений";
	ФайлПроверкаСуществования = Новый Файл(ПутьКФайлу);
	ДвоичныеДанные = Новый ДвоичныеДанные(ПутьКФайлу);
	Возврат ЗагрузитьТелоМодуляВТаблицуЗначенийСервер(ДвоичныеДанные,ШагСтрокДляМодуля);
КонецФункции

&НаСервереБезКонтекста
Процедура ДобавитьНачальноеЗаполнениеВМодульСервер(ТелоМодуля,ШагСтрокДляМодуля,ГенерироватьУФ,ДвДанныеvbFeatureReader,знСоздаватьОбластиПриГенерацииКода)
	ВременноеИмяФайла = ПолучитьИмяВременногоФайла("epf");
	ДвДанныеvbFeatureReader.Записать(ВременноеИмяФайла);
	FeatureReader = ВнешниеОбработки.Создать(ВременноеИмяФайла,Ложь);
	FeatureReader.ДобавитьНачальноеЗаполнениеВМодуль(ТелоМодуля,ШагСтрокДляМодуля,ГенерироватьУФ,Истина,знСоздаватьОбластиПриГенерацииКода);
КонецПроцедуры

&НаКлиенте
Процедура ДобавитьНачальноеЗаполнениеВМодуль(ТелоМодуля,ШагСтрокДляМодуля,ГенерироватьУФ,ДвДанныеvbFeatureReader,ЗнСоздаватьОбластиПриГенерацииКода)
	ДобавитьНачальноеЗаполнениеВМодульСервер(ТелоМодуля,ШагСтрокДляМодуля,ГенерироватьУФ,ДвДанныеvbFeatureReader,ЗнСоздаватьОбластиПриГенерацииКода);
	//ВызватьИсключение "Не реализовано ДобавитьНачальноеЗаполнениеВМодуль";
КонецПроцедуры

&НаКлиенте
Функция НайтиФайлВМассивеФайлов(МассивФайлов,ИмяФайла)
	Для каждого Элем Из МассивФайлов Цикл
		Если НРег(Элем.ПолноеИмя) = НРег(ИмяФайла) Тогда
			Возврат Истина;
		КонецЕсли;	 
	КонецЦикла;
	
	Возврат Ложь;
КонецФункции	

&НаКлиенте
Функция СоздатьСтруктураОписанияEpf(ОтносительныйКаталогФичи,ИмяТекущейФичи,GenerateEpf,ДвДанныеvbFeatureReader,ДополнительныеПараметры)
	КаталогИнструментов = Объект.КаталогИнструментов;
	ГенерироватьУФ      = Объект.ГенерироватьУФ;
	
	СтруктураОписанияEpf                    = СоздатьПустуюСтруктуруEpf();
	СтруктураОписанияEpf.ИмяФичи            = ИмяТекущейФичи;
	СтруктураОписанияEpf.ИмяФайлаEpf        = ДополнитьСлешВПуть(ОтносительныйКаталогФичи) + ДополнитьСлешВПуть("step_definitions") + ИмяТекущейФичи + ".epf";
	Если GenerateEpf Тогда
		ФайлEpf = Новый Файл(СтруктураОписанияEpf.ИмяФайлаEpf);
		Если НЕ ЕстьПоддержкаАсинхронныхВызовов Тогда
			ФайлСуществует = ФайлEpf.Существует();
		Иначе	
			МассивФайлов = ПолучитьЗначениеПоРанееСобраннойИнформации(ДополнительныеПараметры,"ПоискEPF","НайденныеФайлы");
			ФайлСуществует = НайтиФайлВМассивеФайлов(МассивФайлов,СтруктураОписанияEpf.ИмяФайлаEpf);
		КонецЕсли;	 
		Если ФайлСуществует Тогда //т.е. если мы не первый раз работаем с данной фичей
			Если НЕ Объект.ВыводитьТекстМодуляВместоПерегенерацииEPF Тогда
				СтруктураОписанияEpf.ИмяМодуляEpf          = РаспаковатьEPF(СтруктураОписанияEpf);
				СтруктураОписанияEpf.ФайлEpfПересоздавался = Истина;
			КонецЕсли;	 
		КонецЕсли;	 
	КонецЕсли;
	
	Если Не СтруктураОписанияEpf.ФайлEpfПересоздавался Тогда
		СтруктураОписанияEpf.КаталогИсходников = ДополнитьСлешВПуть(КаталогИнструментов) + "lib/TemplateEpf";
		Если ГенерироватьУФ Тогда
			СтруктураОписанияEpf.КаталогИсходников = ДополнитьСлешВПуть(КаталогИнструментов) + "lib/TemplateEpfUF";
		КонецЕсли;	   
	КонецЕсли;	
		
	
	//если уже были исходники, то надо использовать их
	//ПромИмяФайла = ДополнитьСлешВПуть(ОтносительныйКаталогФичи) + ДополнитьСлешВПуть("step_definitions") + ДополнитьСлешВПуть("src") + ИмяТекущейФичи;
	//ПромИсходникиФайл = Новый Файл(СтруктураОписанияEpf.КаталогИсходников);
	
	//Если ФайлСуществуетКомандаСистемы(ПромИсходникиФайл.ПолноеИмя) Тогда
	//	СтруктураОписанияEpf.КаталогИсходников = ПромИмяФайла;
	//КонецЕсли;	 
	
	
	СтруктураОписанияEpf.ВременноеИмяМодуля = ДополнитьСлешВПуть(СтруктураОписанияEpf.КаталогИсходников) + "ObjectModule_" + ИмяТекущейФичи + ".txt";
	Если ГенерироватьУФ Тогда
		СтруктураОписанияEpf.ВременноеИмяМодуля = ДополнитьСлешВПуть(СтруктураОписанияEpf.КаталогИсходников) + "und/70e297e0-e8a2-43bf-8be1-62e408f610a1.0_" + ИмяТекущейФичи + ".txt";
	КонецЕсли;	 
	
	Файл = Новый Файл(СтруктураОписанияEpf.ВременноеИмяМодуля);
	ЗТ = Новый ЗаписьТекста(СтруктураОписанияEpf.ВременноеИмяМодуля,"UTF-8",,Ложь); 
	ЗТ.Закрыть();
	
	Файл = Новый Файл(СтруктураОписанияEpf.ИмяМодуляEpf); //значит надо загрузить модуль из исходников
	
	Если НЕ ЕстьПоддержкаАсинхронныхВызовов Тогда
		ФайлСуществует = Файл.Существует();
	Иначе	
		ФайлСуществует = ФайлСуществуетКомандаСистемы(СтруктураОписанияEpf.ИмяМодуляEpf);
		//МассивФайлов = ПолучитьЗначениеПоРанееСобраннойИнформации(ДополнительныеПараметры,"ПоискFeature","НайденныеФайлы");
		//ФайлСуществует = НайтиФайлВМассивеФайлов(МассивФайлов,Файл.ПолноеИмя);
	КонецЕсли;	 
	Если ФайлСуществует Тогда
		СтруктураОписанияEpf.ТелоМодуля = ЗагрузитьТелоМодуляВТаблицуЗначений(СтруктураОписанияEpf.ИмяМодуляEpf);
	Иначе
		СтруктураОписанияEpf.ТелоМодуля = ЗагрузитьТелоМодуляВТаблицуЗначений(СтруктураОписанияEpf.ВременноеИмяМодуля);
		//значит создаём файл первый разделим
		ДобавитьНачальноеЗаполнениеВМодуль(СтруктураОписанияEpf.ТелоМодуля,ШагСтрокДляМодуля,ГенерироватьУФ,ДвДанныеvbFeatureReader,Объект.СоздаватьОбластиПриГенерацииКода);
	КонецЕсли;
	
	Возврат СтруктураОписанияEpf;
КонецФункции

&НаСервереБезКонтекста
Функция СнипетыПолучитьСнипетыПоШагам(Шаги,ДвДанныеvbFeatureReader)
	ВременноеИмяФайла = ПолучитьИмяВременногоФайла("epf");
	ДвДанныеvbFeatureReader.Записать(ВременноеИмяФайла);
	FeatureReader = ВнешниеОбработки.Создать(ВременноеИмяФайла,Ложь);
	
	Возврат FeatureReader.СнипетыПолучитьСнипетыПоШагам(Шаги);
КонецФункции

&НаСервереБезКонтекста
Процедура ЗаполнитьПроцедуруПолучитьСписокТестов(ТелоМодуля,Снипеты,ДвДанныеvbFeatureReader,ИмяФайлаФичи,СоздаватьЗакоментированныйКодДляПереиспользуемыхПроцедур)
	ВременноеИмяФайла = ПолучитьИмяВременногоФайла("epf");
	ДвДанныеvbFeatureReader.Записать(ВременноеИмяФайла);
	FeatureReader = ВнешниеОбработки.Создать(ВременноеИмяФайла,Ложь);
	
	FeatureReader.ЗаполнитьПроцедуруПолучитьСписокТестов(ТелоМодуля,Снипеты,Истина,ИмяФайлаФичи,СоздаватьЗакоментированныйКодДляПереиспользуемыхПроцедур);
КонецПроцедуры

&НаСервереБезКонтекста
Процедура ДобавитьStepDefinitionВТекстМодуля(СтруктураОписанияEpf,StepDefinition,Шаг,ШагСтрокДляМодуля,АдресСнипета,ГенерироватьУФ,ДвДанныеvbFeatureReader,СоздаватьЗакоментированныйКодДляПереиспользуемыхПроцедур)
	ВременноеИмяФайла = ПолучитьИмяВременногоФайла("epf");
	ДвДанныеvbFeatureReader.Записать(ВременноеИмяФайла);
	FeatureReader = ВнешниеОбработки.Создать(ВременноеИмяФайла,Ложь);
	
	FeatureReader.ДобавитьStepDefinitionВТекстМодуля(СтруктураОписанияEpf,StepDefinition,Шаг,ШагСтрокДляМодуля,АдресСнипета,СоздаватьЗакоментированныйКодДляПереиспользуемыхПроцедур,ГенерироватьУФ,Истина);
КонецПроцедуры


&НаСервере
Функция ПолучитьТелоМодуляВМассивСервер(Стр)
	ТелоМодуля = ЗначениеИзСтрокиВнутр(Стр);
	ТелоМодуля.Сортировать("НомСтр");
	Массив = ТелоМодуля.ВыгрузитьКолонку("Стр");
	
	Возврат Массив;
КонецФункции

&НаКлиенте
Процедура УдалитьИзФайлаМодуляФормыУФТестМодуляФормы(ИмяФайлаФормаУФ)
	Файл = Новый Файл(ИмяФайлаФормаУФ);
	
	Если Не ФайлСуществуетКомандаСистемы(ИмяФайлаФормаУФ) Тогда
		ВызватьИсключение "УдалитьИзФайлаМодуляФормыУФТестМодуляФормы. Файл " + ИмяФайлаФормаУФ + " не найден!";
	КонецЕсли;	 
	
	ВременноеИмяФайла = ПолучитьИмяВременногоФайла("txt");
	//Сообщить("ВременноеИмяФайла=" + ВременноеИмяФайла);
	
	ЗТ = Новый ЗаписьТекста(ВременноеИмяФайла,"UTF-8",,Истина); 
	
	Текст = Новый ЧтениеТекста;
	Текст.Открыть(ИмяФайлаФормаУФ,"UTF-8");
	
	НачалоМодуля = -1;
	КонецМодуля  = -1;
	
	НашлиМодуль = Ложь;
	
	КолСкобок1  = 0;
	КолСкобок2  = 0;
	НомерСтроки = 0;
	Пока Истина Цикл
		Стр = Текст.ПрочитатьСтроку();
		Если Стр = Неопределено Тогда
			Прервать;
		КонецЕсли;	 
		
		НомерСтроки = НомерСтроки + 1;
		
		КолСкобок1 = КолСкобок1 + СтрЧислоВхождений(Стр,"{");
		КолСкобок2 = КолСкобок2 + СтрЧислоВхождений(Стр,"}");
		
		Если (НачалоМодуля > 0) И НЕ НашлиМодуль Тогда
			Если Лев(Стр,1) = "{" Тогда
				КонецМодуля = НомерСтроки;
				ЗТ.ЗаписатьСтроку(""","); 
				ЗТ.ЗаписатьСтроку(Стр); 
				НашлиМодуль = Истина;
				Продолжить;
			КонецЕсли;	 
		КонецЕсли;	 
		
		Если (НомерСтроки > 2) И (НачалоМодуля = -1) И НЕ НашлиМодуль Тогда
			//Если (КолСкобок1 - КолСкобок2) = 1 Тогда //значит сейчас начинается модуль
			Поз = Найти(Стр,"},""");
			Если (Поз > 0) И (Прав(Стр,1) <> ",") Тогда
				НачалоМодуля = НомерСтроки;
				
				НачалоСтроки = Лев(Стр,Поз-1);
				
				ЗТ.ЗаписатьСтроку(НачалоСтроки + "},""//начало текста модуля"); 
				Продолжить;
			КонецЕсли;	 
		КонецЕсли;	 
		
		
		Если (НачалоМодуля > 0) и НЕ НашлиМодуль Тогда
			Продолжить;
		КонецЕсли;	 
		
		ЗТ.ЗаписатьСтроку(Стр); 
		
	КонецЦикла;	
	
	Текст.Закрыть();
	ЗТ.Закрыть();
	
	
	Если Не НашлиМодуль Тогда
		ВызватьИсключение "Не смог найти код модуля формы в файле ИмяФайлаФормаУФ!";
	КонецЕсли;	 
	
	
	Отладка("Копирую файл " + ВременноеИмяФайла + " в " + ИмяФайлаФормаУФ);
	КопироватьФайлКомандаСистемы(ВременноеИмяФайла,ИмяФайлаФормаУФ);
	
КонецПроцедуры

&НаКлиенте
Функция УбратьСпецсимволыИзИмениОбработи(Знач Стр)
	Стр = СтрЗаменить(Стр," ","_");
	Стр = СтрЗаменить(Стр,"`","");
	Стр = СтрЗаменить(Стр,"~","");
	Стр = СтрЗаменить(Стр,"'","");
	Стр = СтрЗаменить(Стр,".","");
	Стр = СтрЗаменить(Стр,",","");
	Стр = СтрЗаменить(Стр,":","");
	Стр = СтрЗаменить(Стр,";","");
	Стр = СтрЗаменить(Стр,"-","_");  
	Стр = СтрЗаменить(Стр,"+","");
	Стр = СтрЗаменить(Стр,"/","");
	Стр = СтрЗаменить(Стр,"\","");
	Стр = СтрЗаменить(Стр,"=","");
	Стр = СтрЗаменить(Стр,"!","");
	Стр = СтрЗаменить(Стр,"@","");
	Стр = СтрЗаменить(Стр,"#","");
	Стр = СтрЗаменить(Стр,"$","");
	Стр = СтрЗаменить(Стр,"%","");
	Стр = СтрЗаменить(Стр,"^","");
	Стр = СтрЗаменить(Стр,"&","");
	Стр = СтрЗаменить(Стр,"*","");
	Стр = СтрЗаменить(Стр,"(","");
	Стр = СтрЗаменить(Стр,")","");
	Стр = СтрЗаменить(Стр,"№","");
	Стр = СтрЗаменить(Стр,"?","");
	Стр = СтрЗаменить(Стр,"<","");
	Стр = СтрЗаменить(Стр,">","");
	
	Возврат Стр;
КонецФункции	

&НаКлиенте
Процедура ЗаменитьСтрокиВФайлеОсновыОбработки(ИмяФайлОсноваОбработки,ИмяФичи)
	Текст = Новый ЧтениеТекста;
	Текст.Открыть(ИмяФайлОсноваОбработки,"UTF-8");
	
	ВременноеИмяФайла = ИмяФайлОсноваОбработки + "_Temp";
	ЗТ = Новый ЗаписьТекста(ВременноеИмяФайла,"UTF-8",,Истина); 
	Пока Истина Цикл
		Стр = Текст.ПрочитатьСтроку();
		Если Стр = Неопределено Тогда
			Прервать;
		КонецЕсли;	 
		
		ИмяОбработки = УбратьСпецсимволыИзИмениОбработи(ИмяФичи);
		Стр = СтрЗаменить(Стр,"TemplateEpf",ИмяОбработки);
		Стр = СтрЗаменить(Стр,"Template epf",ИмяФичи);
		
		ЗТ.ЗаписатьСтроку(Стр); 
	КонецЦикла;
	
	ЗТ.Закрыть();
	Текст.Закрыть();
	Текст = "";
	
	УдалитьФайлыКомандаСистемы(ИмяФайлОсноваОбработки);
	ПереместитьФайлКомандаСистемы(ВременноеИмяФайла,ИмяФайлОсноваОбработки);
	
КонецПроцедуры

&НаКлиенте
Процедура СоздатьКаталогЕслиЕгоНет(Путь)
	Файл = Новый Файл(Путь);
	Если Путь = "" Тогда
		ВызватьИсключение "Передан пустой путь в процедуру ""СоздатьКаталогЕслиЕгоНет""!";
	КонецЕсли;	 
	СоздатьКаталогКомандаСистемы(Путь);
КонецПроцедуры

&НаКлиенте
Процедура КомандаСистемыРаботаСФайлами(Команда)
	ИмяВременногоЛог = ПолучитьИмяВременногоФайла("log");
	ИмяВременнгоФайла = ПолучитьИмяВременногоФайла("bat");
	ЗТ = Новый ЗаписьТекста(ИмяВременнгоФайла,"windows-1251",,Истина); 
	ЗТ.Закрыть();
	
	ЗТ = Новый ЗаписьТекста(ИмяВременнгоФайла,"UTF-8",,Истина); 
	
	ЗТ.ЗаписатьСтроку("chcp 65001"); 
	ЗТ.ЗаписатьСтроку(Команда); 
	ЗТ.Закрыть();
	
	WshShell = Новый COMОбъект("WScript.Shell");
	WshShell.Run(ИмяВременнгоФайла,0,-1);	
	//КомандаСистемы(ИмяВременнгоФайла + " > " + ИмяВременногоЛог);
КонецПроцедуры			

&НаКлиенте
Процедура УдалитьФайлыКомандаСистемы(Знач ИмяФайла) Экспорт
	Если ЕстьПоддержкаАсинхронныхВызовов Тогда
		//КомандаСистемы("DEL """ + ИмяФайла + """");
		Если ЭтоLinux Тогда 
			ИмяФайла = СтрЗаменить(ИмяФайла,"\","/");
			КомандаСистемы("rm -Rf """ + ИмяФайла + """");
		Иначе //КомандаСистемы("DEL """ + ИмяФайла + """");
			ИмяФайла = СтрЗаменить(ИмяФайла,"/","\");
			КомандаСистемыРаботаСФайлами("DEL /Q """ + ИмяФайла + """");
		КонецЕсли;
	Иначе
		УдалитьФайлы(ИмяФайла);
	КонецЕсли;	 
КонецПроцедуры

&НаКлиенте
Процедура УдалитьКаталогКомандаСистемы(Знач ИмяФайла) Экспорт
	Если ЕстьПоддержкаАсинхронныхВызовов Тогда
		Если ЭтоLinux Тогда 
			ИмяФайла = СтрЗаменить(ИмяФайла,"\","/");
			КомандаСистемы("rm -Rf """ + ИмяФайла + """");
		Иначе //КомандаСистемы("DEL """ + ИмяФайла + """");
			
			ИмяФайла = СтрЗаменить(ИмяФайла,"/","\");
			КомандаСистемыРаботаСФайлами("RD /S /Q """ + ИмяФайла + """");
		КонецЕсли;

	Иначе
		УдалитьФайлы(ИмяФайла);
	КонецЕсли;	 
КонецПроцедуры

&НаКлиенте
Процедура ПереместитьФайлКомандаСистемы(Знач Откуда,Знач Куда) Экспорт
	Если ЕстьПоддержкаАсинхронныхВызовов Тогда
		//КомандаСистемы("MOVE """ + Откуда + """ """ + Куда + """");
		Если ЭтоLinux Тогда 
			Откуда = СтрЗаменить(Откуда,"\","/");
			Куда   = СтрЗаменить(Куда,"\","/");
			КомандаСистемы("mv """ + Откуда + """ """ + Куда + """");
		Иначе 
			
			Откуда = СтрЗаменить(Откуда,"/","\");
			Куда   = СтрЗаменить(Куда,"/","\");
			КомандаСистемыРаботаСФайлами("MOVE """ + Откуда + """ """ + Куда + """");
		КонецЕсли;
	Иначе
		ПереместитьФайл(Откуда,Куда);
	КонецЕсли;	 
КонецПроцедуры

&НаКлиенте
Процедура КопироватьФайлКомандаСистемы(Знач Откуда,Знач Куда) Экспорт
	Если ЕстьПоддержкаАсинхронныхВызовов Тогда
		//КомандаСистемы("COPY """ + Откуда + """ """ + Куда + """");
		Если ЭтоLinux Тогда 
			Откуда = СтрЗаменить(Откуда,"\","/");
			Куда   = СтрЗаменить(Куда,"\","/");
			КомандаСистемы("cp r """ + Откуда + """ """ + Куда + """");
		Иначе 

		Откуда = СтрЗаменить(Откуда,"/","\");
		Куда   = СтрЗаменить(Куда,"/","\");
		КомандаСистемыРаботаСФайлами("COPY """ + Откуда + """ """ + Куда + """");
		КонецЕсли;
	Иначе
		КопироватьФайл(Откуда,Куда);
	КонецЕсли;	 
КонецПроцедуры

&НаКлиенте
Процедура СоздатьКаталогКомандаСистемы(Знач ИмяФайла, ДополнительныеПараметрыАсинхронности = Неопределено) Экспорт
	Если ЕстьПоддержкаАсинхронныхВызовов Тогда
		ИмяФайла = СтрЗаменить(ИмяФайла,"/","\");
		Если НЕ ЭтоLinux Тогда 
			КомандаСистемыРаботаСФайлами("MKDIR """ + ИмяФайла + """");
		Иначе 
			ИмяФайла = СтрЗаменить(ИмяФайла,"\","/");
			КомандаСистемы("mkdir -p """ + ИмяФайла + """");
		КонецЕсли;
	Иначе
		СоздатьКаталог(ИмяФайла);
	КонецЕсли;
				
КонецПроцедуры

&НаКлиенте
Функция ФайлСуществуетКомандаСистемы(Знач ИмяФайла,ДопПараметры = Неопределено) Экспорт
	Если ЕстьПоддержкаАсинхронныхВызовов Тогда
		ИмяВременногоЛог = ПолучитьИмяВременногоФайла("log");
		
		Если НЕ ЭтоLinux Тогда
			ИмяФайла = СтрЗаменить(ИмяФайла,"/","\");
		
			ИмяВременнгоФайла = ПолучитьИмяВременногоФайла("bat");
			ЗТ = Новый ЗаписьТекста(ИмяВременнгоФайла,"windows-1251",,Истина); 
			ЗТ.Закрыть();
			
			ЗТ = Новый ЗаписьТекста(ИмяВременнгоФайла,"UTF-8",,Истина); 
			
			ЗТ.ЗаписатьСтроку("chcp 65001"); 
			ЗТ.ЗаписатьСтроку("If Exist """ + ИмяФайла + """ (Echo yes) Else (Echo no)"); 
			ЗТ.Закрыть();
			
			//КомандаСистемы(ИмяВременнгоФайла + " > " + ИмяВременногоЛог);
			WshShell = Новый COMОбъект("WScript.Shell");
			WshShell.Run(ИмяВременнгоФайла + " > " + ИмяВременногоЛог,0,-1);
		Иначе 
			ИмяВременнгоФайла = ПолучитьИмяВременногоФайла("sh");
			ЗТ = Новый ЗаписьТекста(ИмяВременнгоФайла,"UTF-8",Символы.ПС, Истина, Символы.ПС); 
			
			ЗТ.ЗаписатьСтроку("#!/bin/sh");
			СтрокаКоманды = "sh -c 'test -f "+ИмяФайла+" && echo yes || echo no' > "+ИмяВременногоЛог +"";
			ЗТ.ЗаписатьСтроку(СтрокаКоманды); 
			СтрокаКоманды = "sh -c 'test -d "+ИмяФайла+" && echo yes || echo no' >> "+ИмяВременногоЛог +"";
			ЗТ.ЗаписатьСтроку(СтрокаКоманды);
			ЗТ.Закрыть();
			
			КомандаСистемы("sh "+ ИмяВременнгоФайла);
		КонецЕсли;
		
		
		ФайлСуществует = Ложь;
		
		Текст = Новый ЧтениеТекста;
		Текст.Открыть(ИмяВременногоЛог,"UTF-8");
		
		Пока Истина Цикл
			Стр = Текст.ПрочитатьСтроку();
			Если Стр = Неопределено Тогда
				Прервать;
			КонецЕсли;	 
			
			Если Стр = "yes" Тогда
				ФайлСуществует = Истина;
			КонецЕсли;	 
		КонецЦикла;	
		Текст.Закрыть();
		
		Возврат ФайлСуществует;
	Иначе
		ФайлПроверкаСуществования = Новый Файл(ИмяФайла);
		Возврат ФайлПроверкаСуществования.Существует();
	КонецЕсли;	 
КонецФункции	

&НаКлиенте
Процедура СоздатьФайлыОбработок(БылиОшибки,СтруктураОписанияEpf,ДополнительныеПараметры = Неопределено)
	
	ЭтоУФ = Истина;
	ГенерироватьУФ = Объект.ГенерироватьУФ;
	КаталогИнструментов = Объект.КаталогИнструментов;
	ТекстМодуля = "";
	
	ТелоМодуля = СтруктураОписанияEpf.ТелоМодуля;
	Если ЭтоУФ Тогда
		ТелоМодуля = ПолучитьТелоМодуляВМассивСервер(ТелоМодуля);
	Иначе
		ТелоМодуля.Сортировать("НомСтр");
		ТелоМодуля = ТелоМодуля.ВыгрузитьКолонку("Стр");
	КонецЕсли;	 
	
	Если ЭтоLinux Тогда 
		ТекстМодуля = "";
		Для каждого Строка из ТелоМодуля Цикл 
			ТекстМодуля = ТекстМодуля + Символы.ПС + Строка;
		КонецЦикла;
		ТекстовыйДокумент = Новый ТекстовыйДокумент;
		ТекстовыйДокумент.УстановитьТекст(ТекстМодуля);  
		ФайлРеальногоEPF = Новый Файл(СтруктураОписанияEpf.ИмяФайлаEpf);
		ТекстовыйДокумент.Показать();
		Возврат;
	КонецЕсли;
	
	Отладка("Буду записывать " + СтруктураОписанияEpf.ВременноеИмяМодуля);
	
	УдалитьФайлыКомандаСистемы(СтруктураОписанияEpf.ВременноеИмяМодуля);
	Если ГенерироватьУФ Тогда
		ИмяФайлаФормаУФ = ДополнитьСлешВПуть(КаталогИнструментов) + "lib/TemplateEpfUF/und/70e297e0-e8a2-43bf-8be1-62e408f610a1.0_template";
		Если СтруктураОписанияEpf.ФайлEpfПересоздавался Тогда
			ИмяФайлаФормаУФ = ДополнитьСлешВПуть(СтруктураОписанияEpf.КаталогИсходников) + "und/70e297e0-e8a2-43bf-8be1-62e408f610a1.0";
			УдалитьИзФайлаМодуляФормыУФТестМодуляФормы(ИмяФайлаФормаУФ);
			
			ФайлИмяФайлаФормаУФ = Новый Файл(ИмяФайлаФормаУФ);
			Если Не ФайлСуществуетКомандаСистемы(ФайлИмяФайлаФормаУФ.ПолноеИмя) Тогда
				ВызватьИсключение "Ошибка перегенерации EPF. Файл " + ИмяФайлаФормаУФ + " не найден.";
			КонецЕсли;	 
		КонецЕсли;	 
		Текст = Новый ЧтениеТекста;
		Текст.Открыть(ИмяФайлаФормаУФ,"UTF-8");
		
		ЗТ = Новый ЗаписьТекста(СтруктураОписанияEpf.ВременноеИмяМодуля,"UTF-8",,Ложь); 
		Пока Истина Цикл
			Стр = Текст.ПрочитатьСтроку();
			Если Стр = Неопределено Тогда
				Прервать;
			КонецЕсли;	 
			
			ЗТ.ЗаписатьСтроку(Стр); 
			
			Если Найти(Стр,"},""//начало текста модуля") > 0 Тогда
				Для Каждого СтрТелоМодуля Из ТелоМодуля Цикл
					Если СтрТелоМодуля = "//начало текста модуля" Тогда
						Продолжить;
					КонецЕсли;	 
					
					//СделатьСообщение("СтрТелоМодуля.Стр = " + СтрТелоМодуля.Стр);
					СтрТелоМодуля = СтрЗаменить(СтрТелоМодуля,"""","""""");
					ЗТ.ЗаписатьСтроку(СтрТелоМодуля); 
					//ЗТ.Записать(Символы.ПС); 
				КонецЦикла;
			КонецЕсли;	 
		КонецЦикла;	
		
		
		Текст.Закрыть();
		ЗТ.Закрыть();
	Иначе	
		ЗТ = Новый ЗаписьТекста(СтруктураОписанияEpf.ВременноеИмяМодуля,"UTF-8",,Ложь); 
		Для Каждого СтрТелоМодуля Из ТелоМодуля Цикл
			ЗТ.ЗаписатьСтроку(СтрТелоМодуля); 
		КонецЦикла;
		ЗТ.Закрыть();
	КонецЕсли;	 
	Отладка("Записал " + СтруктураОписанияEpf.ВременноеИмяМодуля);
	
	//ПутьКИсходникам = КаталогИнструментов + "\lib\TemplateEpf\";
	//ИмяФайлаМодуляДляСборки = КаталогИнструментов + "\lib\TemplateEpf\ObjectModule.txt";
	
	//ФайлВременноеИмяМодуля = Новый Файл(СтруктураОписанияEpf.ВременноеИмяМодуля);
	ПутьКИсходникам = СтруктураОписанияEpf.КаталогИсходников;
	ИмяФайлаМодуляДляСборки = ДополнитьСлешВПуть(ПутьКИсходникам) + "ObjectModule.txt";
	Если ГенерироватьУФ Тогда
		ИмяФайлаМодуляДляСборки = ДополнитьСлешВПуть(ПутьКИсходникам) + "und/70e297e0-e8a2-43bf-8be1-62e408f610a1.0";
	КонецЕсли;	 
	
	//УдалитьФайлы(ИмяФайлаМодуляДляСборки);
	УдалитьФайлыКомандаСистемы(ИмяФайлаМодуляДляСборки);
	ПереместитьФайлКомандаСистемы(СтруктураОписанияEpf.ВременноеИмяМодуля,ИмяФайлаМодуляДляСборки);
	//ПереместитьФайл(СтруктураОписанияEpf.ВременноеИмяМодуля,ИмяФайлаМодуляДляСборки);
	Отладка("Переименовал в " + ИмяФайлаМодуляДляСборки);
	
	//ИмяФайлОсноваОбработкиTemplate = КаталогИнструментов + "/lib\TemplateEpf\und\79a499cc-1782-4a2f-abe7-61ea4d49fd5a_template";
	//ИмяФайлОсноваОбработки         = КаталогИнструментов + "\lib\TemplateEpf\und\79a499cc-1782-4a2f-abe7-61ea4d49fd5a";
	ИмяФайлОсноваОбработкиTemplate = ДополнитьСлешВПуть(ПутьКИсходникам) + "und/79a499cc-1782-4a2f-abe7-61ea4d49fd5a_template";
	ИмяФайлОсноваОбработки         = ДополнитьСлешВПуть(ПутьКИсходникам) + "und/79a499cc-1782-4a2f-abe7-61ea4d49fd5a";
	Если ГенерироватьУФ Тогда
		ИмяФайлОсноваОбработкиTemplate = ДополнитьСлешВПуть(КаталогИнструментов) + "lib/TemplateEpfUF/und/79a499cc-1782-4a2f-abe7-61ea4d49fd5a_template";
		ИмяФайлОсноваОбработки         = ДополнитьСлешВПуть(КаталогИнструментов) + "lib/TemplateEpfUF/und/79a499cc-1782-4a2f-abe7-61ea4d49fd5a";
	КонецЕсли;	 
	
	Файл_template = Новый Файл(ИмяФайлОсноваОбработкиTemplate);
	//Если Найти(НРег(ИмяФайлОсноваОбработкиTemplate),НРег(Объект.КаталогИнструментов)) > 0 Тогда
	Если ФайлСуществуетКомандаСистемы(ИмяФайлОсноваОбработкиTemplate) Тогда
		//это значит обработка создаётся в первый раз
		//КопироватьФайл(ИмяФайлОсноваОбработкиTemplate,ИмяФайлОсноваОбработки);
		КопироватьФайлКомандаСистемы(ИмяФайлОсноваОбработкиTemplate,ИмяФайлОсноваОбработки);
		ЗаменитьСтрокиВФайлеОсновыОбработки(ИмяФайлОсноваОбработки,СтруктураОписанияEpf.ИмяФичи);
	КонецЕсли;	 
	
	ИмяВременнойEPF = ПолучитьИмяВременногоФайла("epf");
	ФайлРеальногоEPF = Новый Файл(СтруктураОписанияEpf.ИмяФайлаEpf);
	СоздатьКаталогЕслиЕгоНет(ФайлРеальногоEPF.Путь);
	
	Если НЕ ЕстьПоддержкаАсинхронныхВызовов Тогда
		ФайлУжеЕсть = ФайлРеальногоEPF.Существует();
	Иначе	
		МассивФайлов = ПолучитьЗначениеПоРанееСобраннойИнформации(ДополнительныеПараметры,"ПоискFeature","НайденныеФайлы");
		ФайлУжеЕсть  = НайтиФайлВМассивеФайлов(МассивФайлов,ФайлРеальногоEPF.ПолноеИмя);
	КонецЕсли;	 
	
	Если ФайлУжеЕсть Тогда
		СделатьСообщение("Пересоздаю " + СтруктураОписанияEpf.ИмяФайлаEpf);
	Иначе	
		СделатьСообщение("Создаю " + СтруктураОписанияEpf.ИмяФайлаEpf);
	КонецЕсли; 
	СтрокаЗапуска = ?(ЭтоLinux = Истина,  "python3", "python");
	
	Отладка("Создаю из исходников " + ПутьКИсходникам + " 
		| Временный epf " + ИмяВременнойEPF);
		
	ФайлЛога = ПолучитьИмяВременногоФайла("txt");	
	СтрокаСборкиEpf = СтрокаЗапуска + " " + ДополнитьСлешВПуть(КаталогИнструментов) + "vendor/precommit1c/pyv8unpack.py --compile """ +  ПутьКИсходникам  + """ """ + ИмяВременнойEPF + """ > " + ФайлЛога + " 2>&1";
	
	Отладка("СтрокаСборкиEpf="+СтрокаСборкиEpf);
	
	ФайлВременногоEPF = Новый Файл(ИмяВременнойEPF);
	
	ВыполнитьКомандуОС(СтрокаСборкиEpf);
	
	СтрокаЛогаСборки = ПолучитьТекстовыйФайлОднойСтрокой(ФайлЛога);
	Отладка("Лог командны сборки EPF:" + Символы.ПС + СтрокаЛогаСборки);
	
	Если ФайлСуществуетКомандаСистемы(ФайлВременногоEPF.ПолноеИмя) Тогда
		Если ФайлСуществуетКомандаСистемы(ФайлРеальногоEPF.ПолноеИмя) Тогда
			УдалитьФайлыКомандаСистемы(ФайлРеальногоEPF.ПолноеИмя);
		КонецЕсли;	 
		КопироватьФайлКомандаСистемы(ФайлВременногоEPF.ПолноеИмя,ФайлРеальногоEPF.ПолноеИмя);
		Отладка("Файл " + ФайлРеальногоEPF.ПолноеИмя + " создан.");
	Иначе	
		СделатьСообщение("Ошибка создания файла " + ФайлРеальногоEPF.ПолноеИмя + "!!!");
		БылиОшибки = Истина;
	КонецЕсли;	 
	УдалитьФайлыКомандаСистемы(ИмяФайлаМодуляДляСборки);
	УдалитьФайлыКомандаСистемы(ИмяФайлОсноваОбработки);
	УдалитьФайлыКомандаСистемы(ФайлВременногоEPF.ПолноеИмя);
	
КонецПроцедуры

&НаКлиенте
Функция ПолучитьТекстовыйФайлОднойСтрокой(ИмяФайла)
	Если НЕ ФайлСуществуетКомандаСистемы(ИмяФайла) Тогда
		Возврат Неопределено;
	КонецЕсли;	 
	
	Текст = Новый ЧтениеТекста;
	Текст.Открыть(ИмяФайла,"UTF-8");
	Возврат Текст.Прочитать();
КонецФункции	

&НаКлиенте
Процедура УдалитьИсходникиEPF(ИмяФайлаEpf)
	ФайлEpf = Новый Файл(ИмяФайлаEpf);
	Если Не ФайлСуществуетКомандаСистемы(ФайлEpf.ПолноеИмя) Тогда
		ВызватьИсключение "Файл " + ИмяФайлаEpf + " не существует!";
	КонецЕсли;	 
	
	Путь = ФайлEpf.Путь + "Src";
	УдалитьКаталогКомандаСистемы(Путь);
	
КонецПроцедуры

&НаКлиенте
Процедура СделатьGenerateEpf(СтруктураПараметров)
	
	Если Не ВПеременнойPathЕстьUnpackV8_exe() Тогда
		Сообщить("В переменной PATH не указан путь к ""v8unpack.exe"". Невозможно сделать сбор epf из исходников.");
		Возврат;
	КонецЕсли;	 
	
	Если Не УстановленПитон() Тогда
		Сообщить("Для генерации EPF должен быть установлен Питон. В cmd должна выполняться команда: python --version");
		Возврат;
	КонецЕсли;	 
	
	ГенерироватьУФ          = СтруктураПараметров.ГенерироватьУФ;
	ШагСтрокДляМодуля       = СтруктураПараметров.ШагСтрокДляМодуля;
	DebugLog                = СтруктураПараметров.DebugLog;
	КаталогФич              = СтруктураПараметров.КаталогФич;
	КонтекстVanessaBehavoir = СтруктураПараметров.КонтекстVanessaBehavoir;
	КаталогиБиблиотек       = СтруктураПараметров.КаталогиБиблиотек;
	ДвДанныеvbFeatureReader = СтруктураПараметров.ДвДанныеvbFeatureReader;
	
	ДополнительныеПараметры = Неопределено;
	Если СтруктураПараметров.Свойство("ДополнительныеПараметры") Тогда
		ДополнительныеПараметры = СтруктураПараметров.ДополнительныеПараметры;
	КонецЕсли;	 
	
	СоздаватьЗакоментированныйКодДляПереиспользуемыхПроцедур       = СтруктураПараметров.СоздаватьЗакоментированныйКодДляПереиспользуемыхПроцедур;
	
	
	ПолучитьУжеСуществующиеСнипетыИзОбработок(КаталогФич,ДополнительныеПараметры);
	Для каждого Элем Из КаталогиБиблиотек Цикл
		ПолучитьУжеСуществующиеСнипетыИзОбработок(Элем.Значение,ДополнительныеПараметры);
	КонецЦикла;
	
	
	МассивФич   = СтруктураПараметров.МассивФич;
	МассивШагов = СтруктураПараметров.МассивШагов;
	Ном = 0;
	Для каждого ИмяФайлаФичи Из МассивФич Цикл
		Ном = Ном+1;
		Шаги = МассивШагов.Получить(Ном-1);
		
		ФайлФичи       = Новый Файл(ИмяФайлаФичи);
		ИмяТекущейФичи = ФайлФичи.ИмяБезРасширения;
		СделатьСообщение("Работаю по фиче: " + ИмяФайлаФичи);
		
		МассивДляСозданияEpf = Новый Массив;
		ОтносительныйКаталогФичи = ФайлФичи.Путь;
		Если Найти(Прав(ОтносительныйКаталогФичи,1), "\/") > 0 Тогда
			ОтносительныйКаталогФичи = Лев(ОтносительныйКаталогФичи,СтрДлина(ОтносительныйКаталогФичи)-1);
		КонецЕсли;	 
		
		Отладка("ОтносительныйКаталогФичи=" + ОтносительныйКаталогФичи);
		СтруктураОписанияEpf = СоздатьСтруктураОписанияEpf(ОтносительныйКаталогФичи,ФайлФичи.ИмяБезРасширения,Истина,ДвДанныеvbFeatureReader,ДополнительныеПараметры);
		
		Снипеты = СнипетыПолучитьСнипетыПоШагам(Шаги,ДвДанныеvbFeatureReader);
		ЗаполнитьПроцедуруПолучитьСписокТестов(СтруктураОписанияEpf.ТелоМодуля,Снипеты,ДвДанныеvbFeatureReader,ИмяФайлаФичи,СоздаватьЗакоментированныйКодДляПереиспользуемыхПроцедур);
		Для каждого ЭлемСнипет Из Снипеты Цикл
			ДобавитьStepDefinitionВТекстМодуля(СтруктураОписанияEpf,ЭлемСнипет.StepDefinition,ЭлемСнипет.Шаг,ШагСтрокДляМодуля,ЭлемСнипет.АдресСнипета,ГенерироватьУФ,ДвДанныеvbFeatureReader,СоздаватьЗакоментированныйКодДляПереиспользуемыхПроцедур);
		КонецЦикла;
		
		БылиОшибки = Ложь;
		
		Если Объект.ВыводитьТекстМодуляВместоПерегенерацииEPF Тогда
			ВывестиТекстМодуляНаЭкран(СтруктураОписанияEpf);
		Иначе	
			СоздатьФайлыОбработок(БылиОшибки,СтруктураОписанияEpf,ДополнительныеПараметры);
		КонецЕсли;	 
		
		Если СтруктураОписанияEpf.ФайлEpfПересоздавался Тогда
			УдалитьИсходникиEPF(СтруктураОписанияEpf.ИмяФайлаEpf);
		КонецЕсли;	 
	КонецЦикла; 	
	СделатьСообщение("Создание epf по фичам закончено.");
	
КонецПроцедуры

&НаСервереБезКонтекста
Функция ПолучитьТекстМодуляИзСтруктураОписанияEpfСервер(ТекстМодуляВнутр)
	Стр = "";
	
	Тзн = ЗначениеИзСтрокиВнутр(ТекстМодуляВнутр);
	
	Для каждого СтрТзн Из Тзн Цикл
		Стр = Стр + СтрТзн.Стр + Символы.ПС;
	КонецЦикла;
	
	Возврат Стр;
КонецФункции	

&НаКлиенте
Процедура ВывестиТекстМодуляНаЭкран(СтруктураОписанияEpf)
	Стр = ПолучитьТекстМодуляИзСтруктураОписанияEpfСервер(СтруктураОписанияEpf.ТелоМодуля);
	ТекстовыйДокумент = новый ТекстовыйДокумент;
	ТекстовыйДокумент.ДобавитьСтроку(Стр);
	ТекстовыйДокумент.Показать();
КонецПроцедуры

&НаКлиенте
Процедура СоздатьEPFПоМассивуФич(СтруктураПараметров)
	СделатьСообщение("Запускаю генерацию epf.");
	СделатьGenerateEpf(СтруктураПараметров);
КонецПроцедуры

&НаКлиенте
Процедура СоздатьШаблоныОбработокПродолжение(ДополнительныеПараметры = Неопределено)
	Если Не Объект.РежимСамотестирования Тогда
		ОчиститьСообщения();
	КонецЕсли;  
	СделатьПараметрыКорректными();	
	
	ДвДанныеvbFeatureReader = Новый ДвоичныеДанные(ПолучитьПутьКFeatureReader());
	
	СтруктураПараметров = Новый Структура;
	СтруктураПараметров.Вставить("КаталогИнструментов",Объект.КаталогИнструментов);
	СтруктураПараметров.Вставить("КаталогФич",Объект.КаталогФич);
	СтруктураПараметров.Вставить("DebugLog",Объект.DebugLog);
	СтруктураПараметров.Вставить("ГенерироватьУФ",Объект.ГенерироватьУФ);
	СтруктураПараметров.Вставить("СоздаватьОбластиПриГенерацииКода",Объект.СоздаватьОбластиПриГенерацииКода);
	СтруктураПараметров.Вставить("ШагСтрокДляМодуля",ШагСтрокДляМодуля);
	//СтруктураПараметров.Вставить("КонтекстVanessaBehavoir",ЭтаФорма);
	СтруктураПараметров.Вставить("КаталогиБиблиотек",Объект.КаталогиБиблиотек);
	СтруктураПараметров.Вставить("СоздаватьЗакоментированныйКодДляПереиспользуемыхПроцедур",Объект.СоздаватьЗакоментированныйКодДляПереиспользуемыхПроцедур);
	
	МассивФич   = Новый Массив;
	МассивШагов = Новый Массив;
	ПолучитьСписокФичПоДеревуИСоздатьEPFПоМассивуФич(СтруктураПараметров,МассивФич,МассивШагов);
	
	СтруктураПараметров.Вставить("МассивФич",МассивФич);
	СтруктураПараметров.Вставить("МассивШагов",МассивШагов);
	СтруктураПараметров.Вставить("ДвДанныеvbFeatureReader",ДвДанныеvbFeatureReader);
	СтруктураПараметров.Вставить("ДополнительныеПараметры",ДополнительныеПараметры);
	
	СоздатьEPFПоМассивуФич(СтруктураПараметров);
	ЭтаФорма.Активизировать();
	
КонецПроцедуры

&НаКлиенте
Процедура СоздатьШаблоныОбработок() Экспорт
	
	МассивДействий = Новый Массив;
	ДобавитьМассивСостоянийФайлов(МассивДействий);
	ДобавитьСканированиеКаталогов(МассивДействий);
	
	ДопПараметры = Новый Структура;
	ДопПараметры.Вставить("ТекИдМассива",0);
	ДопПараметры.Вставить("МассивДействий",МассивДействий);
	ДопПараметры.Вставить("НадоЗагрузитьФичи",Ложь);
	ДопПараметры.Вставить("НадоГенерироватьEPF",Истина);
	Если ЕстьПоддержкаАсинхронныхВызовов Тогда
		ПолучитьАсинхроноСостоянияОбъектовФайловойСистемы(ДопПараметры);
	Иначе
		ПолучитьСинхроноСостоянияОбъектовФайловойСистемы(ДопПараметры);
		СоздатьШаблоныОбработокПродолжение();
	КонецЕсли;	 
	
КонецПроцедуры

&НаКлиенте
Процедура СоздатьШаблоныОбработокКоманда(Команда)
	СоздатьШаблоныОбработок();
КонецПроцедуры

// Функция ДополнитьСлешВПуть
//
// Параметры:
// ИмяКаталога
//
// Описание:
// Функция дополняет и возвращает слеш в путь в конец строки, если он отсутствует
//
&НаКлиенте
Функция ДополнитьСлешВПуть(Знач Каталог)
	разделитель = "\";
	
	//СисИнфо = Новый СистемнаяИнформация;
	//Если Найти(Строка(СисИнфо.ТипПлатформы), "Linux")>0 Тогда
	Если ЭтоLinux Тогда
		разделитель = "/";
	КонецЕсли;
		
	Если Прав(Каталог, 1) <> разделитель Тогда
		Каталог = Каталог + разделитель;
	КонецЕсли;
	Возврат Каталог;
КонецФункции


&НаСервере
Функция ПолучитьКлючиЗаписиРСПоНаборуЗаписейРС(НаборЗаписей,ИмяРС)
	Результат = Новый Массив;
	
	Периодический        = Не (Метаданные.РегистрыСведений[ИмяРС].ПериодичностьРегистраСведений = Метаданные.СвойстваОбъектов.ПериодичностьРегистраСведений.Непериодический);
	ПодчиненРегистратору = (Метаданные.РегистрыСведений[ИмяРС].РежимЗаписи = Метаданные.СвойстваОбъектов.РежимЗаписиРегистра.ПодчинениеРегистратору);
	
	МассивИзмерений = Новый Массив;
	Для каждого Измерение Из Метаданные.РегистрыСведений[ИмяРС].Измерения Цикл
		МассивИзмерений.Добавить(Измерение.Имя);
	КонецЦикла;
	
	Для каждого Запись Из НаборЗаписей Цикл
		ЗначениеКлюча = Новый Структура;
		
		Если ПодчиненРегистратору Тогда
			ЗначениеКлюча.Вставить("Регистратор",Запись.Регистратор);
		КонецЕсли;	 
		Если Периодический Тогда
			ЗначениеКлюча.Вставить("Период",Запись.Период);
		КонецЕсли;	 
		
		Для каждого Измерение Из МассивИзмерений Цикл
			ЗначениеКлюча.Вставить(Измерение,Запись[Измерение]);
		КонецЦикла;
		
		
		ПараметрыКонструктора = Новый Массив();      
		ПараметрыКонструктора.Добавить(ЗначениеКлюча);      
		КлючЗаписи =  Новый("РегистрСведенийКлючЗаписи." + ИмяРС, ПараметрыКонструктора);		
		
		Результат.Добавить(КлючЗаписи);
	КонецЦикла;
	
	Возврат Результат;
	
КонецФункции	

//} МЕТОДЫ ДЛЯ ПРОВЕРКИ ЗНАЧЕНИЙ (assertions). 


//портирован блок генерации данных из проекта xUnitFor1C (https://github.com/xDrivenDevelopment/xUnitFor1C)
//был взят релиз 3.0.0.3
// { Методы генерации тестовых данных

// количествоСозданныхОбъектов учитывает только созданные элементы справочников, документы и пользователей ИБ. Записи регистров сведений не считаются!
&НаКлиенте
Функция СоздатьДанныеПоТабличномуДокументу(ТабличныйДокумент, РежимыЗагрузкиИлиИмяКолонкиЗамещения = Неопределено, ИмяКолонкиЗамещения = Неопределено) Экспорт
	Данные = СоздатьДанныеПоТабличномуДокументуСервер(ТабличныйДокумент, РежимыЗагрузкиИлиИмяКолонкиЗамещения, ИмяКолонкиЗамещения);
	Возврат Данные;
КонецФункции


&НаСервере
Функция СоздатьДанныеПоТабличномуДокументуСервер(ТабличныйДокумент, РежимыЗагрузкиИлиИмяКолонкиЗамещения, ИмяКолонкиЗамещения) //Экспорт
	Данные = Объект().СоздатьДанныеПоТабличномуДокументу(ТабличныйДокумент, РежимыЗагрузкиИлиИмяКолонкиЗамещения, ИмяКолонкиЗамещения);
	
	Для каждого Элем Из Данные Цикл
		Стр = Строка(Элем.Значение);
		Если Найти(Стр,"РегистрСведенийНаборЗаписей") > 0 Тогда
			ИмяРС = Сред(Стр,29);
			Данные[Элем.Ключ] = ПолучитьКлючиЗаписиРСПоНаборуЗаписейРС(Элем.Значение,ИмяРС);
		КонецЕсли;	 
	КонецЦикла;
	
	Возврат Данные;
	//Возврат Неопределено; //Данные;
КонецФункции
//}

// { работа с данными текущего теста

&НаКлиенте
Процедура УстановитьДанныеТекущегоТеста(ДанныеТекущегоТеста)
	
	//УстановитьКонтекст(ДанныеТекущегоТеста, ИдентификаторКонтекстаДанныхТекущегоТеста());
	
КонецПроцедуры

&НаКлиенте
Процедура УдалитьДанныеТекущегоТеста()
	
	//УдалитьКонтекст(ИдентификаторКонтекстаДанныхТекущегоТеста());
	
КонецПроцедуры

&НаКлиенте
Функция ПустыеДанныеТекущегоТеста()
	
	ДанныеТеста = Новый Структура;
	ДанныеТеста.Вставить("Имя", "");
	ДанныеТеста.Вставить("ПолныйПуть", "");
	ДанныеТеста.Вставить("СостояниеТеста", "");
	
	Возврат ДанныеТеста;
	
КонецФункции

Функция ИдентификаторКонтекстаДанныхТекущегоТеста()
	
	Возврат "xUnitFor1C_ДанныеТекущегоТеста";
	
КонецФункции

// }


&НаКлиенте
Функция НайтиСтрокуСценарияЧерезРодителя(СтрокаДерева)
	Пока Истина Цикл
		СтрокаДерева = СтрокаДерева.ПолучитьРодителя();
		Если СтрокаДерева = Неопределено Тогда
			Возврат Неопределено;
		КонецЕсли;	 
		
		Если СтрокаДерева.Сценарий = Истина Тогда
			Возврат СтрокаДерева;
		КонецЕсли;	 
	КонецЦикла;
КонецФункции	

&НаКлиенте
Процедура ВыполнитьВыделенныйСценарий(Команда)
	СтрокаСценария = Элементы.ДеревоТестов.ТекущиеДанные;
	Если СтрокаСценария = Неопределено Тогда
		Возврат;
	КонецЕсли; 
	
	Если СтрокаСценария.Сценарий <> Истина Тогда
		СтрокаСценария = НайтиСтрокуСценарияЧерезРодителя(СтрокаСценария);
		Если СтрокаСценария = Неопределено Тогда
			Сообщить("Не найден строка сценария!");
			Возврат;
		КонецЕсли;	 
	КонецЕсли;	 
	
	ИД = СтрокаСценария.ИДСтроки;
	ВыполнитьСценарии(ИД);

КонецПроцедуры

&НаКлиенте
Процедура ПерезагрузитьИВыполнить(Команда)
	Если НЕ ЕстьПоддержкаАсинхронныхВызовов Тогда
		ЗагрузитьФичи();
		ВыполнитьСценарии();
	Иначе
		Объект.НадоВыполнитьСценарииПослеЗагрузкиФичОдинРаз = Истина;
		ЗагрузитьФичи();
	КонецЕсли;	 
КонецПроцедуры

&НаКлиенте
Процедура ОбработатьЗапускПриложения(КодВозврата,ДополнительныеПараметры) Экспорт
КонецПроцедуры

&НаКлиенте
Функция НайтиСтрокуФичиЧерезРодителя(Стр)
	СтрокаДерева = Стр;
	Пока Истина Цикл
		СтрокаДерева = СтрокаДерева.ПолучитьРодителя();
		Если СтрокаДерева = Неопределено Тогда
			Возврат Неопределено;
		КонецЕсли;	 
		
		Если СтрокаДерева.Фича = Истина Тогда
			Возврат СтрокаДерева;
		КонецЕсли;	 
	КонецЦикла;
КонецФункции	

&НаКлиенте
Процедура ОткрытьФичаФайл(Команда)
	СтрокаФичи = Элементы.ДеревоТестов.ТекущиеДанные;
	Если СтрокаФичи = Неопределено Тогда
		Возврат;
	КонецЕсли; 
	
	Если СтрокаФичи.Фича <> Истина Тогда
		СтрокаФичи = НайтиСтрокуФичиЧерезРодителя(СтрокаФичи);
		Если СтрокаФичи = Неопределено Тогда
			Сообщить("Строка с фича-файлом не найдена!");
			Возврат;
		КонецЕсли;	 
	КонецЕсли;	 
	
	Если ЕстьПоддержкаАсинхронныхВызовов Тогда
		ОписаниеОповещения = Вычислить("Новый ОписаниеОповещения(""ОбработатьЗапускПриложения"", ЭтаФорма)");
		Выполнить("НачатьЗапускПриложения(ОписаниеОповещения,СтрокаФичи.ПолныйПуть)");
	Иначе	
		ЗапуститьПриложение(СтрокаФичи.ПолныйПуть);
	КонецЕсли;  
	
КонецПроцедуры


&НаКлиенте
Функция ЭтаФормаTestClientУжеОбрабатывалась(ИмяТекущейФормыTestClient)
	Для каждого Элем Из МассивСостояниеФормTestClient Цикл
		Если Элем.ИмяФормы = ИмяТекущейФормыTestClient Тогда
			Возврат Истина;
		КонецЕсли;	 
	КонецЦикла;
	
	Возврат Ложь;
КонецФункции	

&НаКлиенте
Функция ПолучитьАктивноеОкноИзТестовоеПриложение()
	Возврат ОбъектКонтекстСохраняемый.ТестовоеПриложение.ПолучитьАктивноеОкно();
КонецФункции	

Функция ПолучитьТекстЗаголовокРеквизитаРодитель(ТекстЗаголовка,ИмяРодителя)
	Возврат ТекстЗаголовка + "_" + ИмяРодителя;
КонецФункции	

&НаКлиенте
Функция ПолучитьСвойстваОбъекта(ЭлементФормы,МассивЗаголовковПолей,МассивЗаголовковКнопок,ИмяРодителя)
	Рез = Новый Структура;
	Рез.Вставить("Имя",ЭлементФормы.Имя);
	Рез.Вставить("ТекстЗаголовка",ЭлементФормы.ТекстЗаголовка);
	Рез.Вставить("ИмяРодителя",ИмяРодителя);
	
	Если ТипЗнч(ЭлементФормы) = Тип("ТестируемоеПолеФормы") Тогда
		//Стр = ПолучитьТекстЗаголовокРеквизитаРодитель(ЭлементФормы.ТекстЗаголовка,ИмяРодителя);
		МассивЗаголовковПолей.Добавить(ЭлементФормы.ТекстЗаголовка);
	ИначеЕсли ТипЗнч(ЭлементФормы) = Тип("ТестируемаяКнопкаФормы") Тогда
		//Стр = ПолучитьТекстЗаголовокРеквизитаРодитель(ЭлементФормы.ТекстЗаголовка,ИмяРодителя);
		МассивЗаголовковКнопок.Добавить(ЭлементФормы.ТекстЗаголовка);
	КонецЕсли;	 
	
	Возврат Рез;
КонецФункции	

&НаКлиенте
Функция ПолучитьЭлементыФормыИерархически(Элементформы,МассивЗаголовковПолей,МассивЗаголовковКнопок)
	Рез = Новый Массив;
	
	НайденныеОбъекты = Элементформы.ПолучитьПодчиненныеОбъекты();
	Для каждого Элем Из НайденныеОбъекты Цикл
		//Сообщить("Получаю ПодчиненныеОбъекты для " + Элем.Имя);
		
		
		
		Если ТипЗнч(Элементформы) = Тип("ТестируемаяФорма") Тогда
			СвойстваОбъекта = ПолучитьСвойстваОбъекта(Элем,МассивЗаголовковПолей,МассивЗаголовковКнопок,Элементформы.ИмяФормы);
		ИначеЕсли ТипЗнч(Элементформы) = Тип("ТестируемаяТаблицаФормы") Тогда
			Продолжить;
		Иначе	
			СвойстваОбъекта = ПолучитьСвойстваОбъекта(Элем,МассивЗаголовковПолей,МассивЗаголовковКнопок,Элементформы.Имя);
		КонецЕсли;	 
		
		Рез.Добавить(СвойстваОбъекта);
		
		ПодчиненныеОбъекты = ПолучитьЭлементыФормыИерархически(Элем,МассивЗаголовковПолей,МассивЗаголовковКнопок);
		СвойстваОбъекта.Вставить("ПодчиненныеОбъекты",ПодчиненныеОбъекты);
		
	КонецЦикла;
	
	Возврат Рез;
КонецФункции

&НаКлиенте
Процедура ДобавитьСостояниеФормыTestclient(ТекущаяФорма)
	СостояниеФормы = Новый Структура;
	СостояниеФормы.Вставить("ИмяФормы",ТекущаяФорма.ИмяФормы);
	СостояниеФормы.Вставить("ТекстЗаголовка",ТекущаяФорма.ТекстЗаголовка);
	МассивЗаголовковПолей = Новый Массив;
	СостояниеФормы.Вставить("МассивЗаголовковПолей",МассивЗаголовковПолей);
	
	МассивЗаголовковКнопок = Новый Массив;
	СостояниеФормы.Вставить("МассивЗаголовковКнопок",МассивЗаголовковКнопок);
	
	
	МассивСостояниеФормTestClient.Добавить(СостояниеФормы);
	Попытка
		
		МассивОбъектов = ПолучитьЭлементыФормыИерархически(ТекущаяФорма,МассивЗаголовковПолей,МассивЗаголовковКнопок);
		
	Исключение
		Сообщить("" + ОписаниеОшибки());
	КонецПопытки;
	
	СостояниеФормы.Вставить("МассивОбъектов",МассивОбъектов);
	Отладка("Добавил форму: " + ТекущаяФорма.ИмяФормы);
КонецПроцедуры

&НаКлиенте
Процедура ЗаполнитьСостояниеТекущейФормыTestClient()
	ОкноПриложения = ПолучитьАктивноеОкноИзТестовоеПриложение();
	МассивФорм     = ОкноПриложения.НайтиОбъекты(Тип("ТестируемаяФорма"));
	Для каждого ТекущаяФорма Из МассивФорм Цикл
		ИмяТекущейФормыTestClient = ТекущаяФорма.ИмяФормы;
		
		Если ЭтаФормаTestClientУжеОбрабатывалась(ИмяТекущейФормыTestClient) Тогда
			Возврат;
		КонецЕсли;	 
		
		ДобавитьСостояниеФормыTestclient(ТекущаяФорма);
	КонецЦикла;
	
	
КонецПроцедуры

&НаКлиенте
Процедура ОпросЭлементовФормTestClient()
	Если ИдетОпросЭлементовФормTestClient Тогда
		Возврат;
	КонецЕсли;	 
	
	ИдетОпросЭлементовФормTestClient = Истина;
	
	
	
	Попытка
	
		ЗаполнитьСостояниеТекущейФормыTestClient();
	
	Исключение
		Отладка("" + ОписаниеОшибки());
	КонецПопытки;
	
	
	
	ИдетОпросЭлементовФормTestClient = Ложь;
КонецПроцедуры

&НаКлиенте
Процедура НачатьЗаписьДействийПользователя() Экспорт 
	ОткрытьНовыйСеансTestClientИлиПодключитьУжеСуществующий();
	Попытка
		ОбъектКонтекстСохраняемый.ТестовоеПриложение.НачатьЗаписьЖурналаДействийПользователя();
		СделатьСообщение("Запись действий пользователя начата.");
	Исключение
		Сообщить("" + ОписаниеОшибки());
		Возврат;
	КонецПопытки;
	
	ИдетОпросЭлементовФормTestClient = Ложь;
	МассивСостояниеФормTestClient    = Новый Массив;
	ПодключитьОбработчикОжидания("ОпросЭлементовФормTestClient", 1);
КонецПроцедуры



&НаКлиенте
Процедура НачатьЗаписьДействийПользователяКнопка(Команда)
	НачатьЗаписьДействийПользователя();
КонецПроцедуры

&НаСервереБезКонтекста
Функция ПолучитьКод1СИзUILogToScriptСервер(ДвоичныеДанные,Стр)
	ИмяВременногоEPF = ПолучитьИмяВременногоФайла("epf");
	ДвоичныеДанные.Записать(ИмяВременногоEPF);
	
	Обработка                           = ВнешниеОбработки.Создать(ИмяВременногоEPF);
	Обработка.ObjectSearch              = 2;
	Обработка.SplitScriptIntoProcedures = Истина;
	Обработка.MainProcedureName         = "ВыполнитьДействия";
	
	Возврат Обработка.Convert(Стр);
	
КонецФункции	

&НаКлиенте
Процедура ОбработатьПолученныйКодUILogToScript(Стр)
	Стр = СтрЗаменить(Стр,"ТестовоеПриложение.НайтиОбъект","КонтекстСохраняемый.ТестовоеПриложение.НайтиОбъект");
	Стр = СтрЗаменить(Стр,"ТестовоеПриложение.ПолучитьПодчиненныеОбъекты()","КонтекстСохраняемый.ТестовоеПриложение.ПолучитьПодчиненныеОбъекты()");
КонецПроцедуры

&НаКлиенте
Функция ПолучитьПервоеКлючевоеСлово(СчетчикДействий,ТипДействия = Неопределено)
	СчетчикДействий = СчетчикДействий + 1;
	Если (СчетчикДействий > 1) и (ТипДействия = "ОткрытиеОкна") Тогда
		Возврат "	Тогда";
	КонецЕсли;	 
	
	Если СчетчикДействий = 1 Тогда
		Возврат "	Когда";
	Иначе
		Возврат "	И    ";
	КонецЕсли;	 
КонецФункции	

&НаКлиенте
Функция ПолучитьТекстФичиИзКодаUILogToScriptOld(Знач Стр)
	Результат = "# encoding: utf-8
	|# language: ru
	|
	|Функционал: <описание фичи>
	|
	|Как <Роль> я хочу
	|<описание функционала> 
	|чтобы <бизнес-эфект> 
	|
	|Сценарий: <описание сценария> 
	|
	|";
	
	
	
	ИмяФайла = ПолучитьИмяВременногоФайла("txt");
	ЗТ = Новый ЗаписьТекста(ИмяФайла,"UTF-8",,Истина); 
	ЗТ.ЗаписатьСтроку(Стр); 
	ЗТ.Закрыть();
	
	Текст = Новый ЧтениеТекста;
	Текст.Открыть(ИмяФайла,"UTF-8");
	
	СтрПоиска = "";
	
	ТипДействия = "";
	ИмяОкнаТестируемоеОкноКлиентскогоПриложения = "";
	ИмяТестируемойФормы                         = "";
	ИмяЭлементаФормы                            = "";
	СчетчикДействий                             = 0;
	Пока Истина Цикл
		Стр = Текст.ПрочитатьСтроку();
		Если Стр = Неопределено Тогда
			Прервать;
		КонецЕсли;	 
		
		Если Найти(НРег(Стр),НРег("ОкноПриложенияОсновноеCommandInterface.НайтиОбъект(Тип(""ТестируемаяКнопкаКомандногоИнтерфейса"")")) > 0 Тогда
			//это нажатие кнопки командного интерфейса
			ТипДействия = "ТестируемаяКнопкаКомандногоИнтерфейса";
			Поз = Найти(НРег(Стр),НРег("ОкноПриложенияОсновноеCommandInterface.НайтиОбъект(Тип(""ТестируемаяКнопкаКомандногоИнтерфейса"")"));
			
			ПромСтр = Сред(Стр,Поз);
			ПромСтр = СтрЗаменить(ПромСтр,"ОкноПриложенияОсновноеCommandInterface.НайтиОбъект(Тип(""ТестируемаяКнопкаКомандногоИнтерфейса""),","");
			
			ПромСтр = СтрЗаменить(ПромСтр,");","");
			ПромСтр = СтрЗаменить(ПромСтр,"""","");
			ПромСтр = СокрЛП(ПромСтр);
			
			Результат = Результат + ПолучитьПервоеКлючевоеСлово(СчетчикДействий) + " Я нажимаю кнопку командного интерфейса """ + ПромСтр + """" + Символы.ПС;
		ИначеЕсли Найти(НРег(Стр),НРег("ТестовоеПриложение.НайтиОбъект(Тип(""ТестируемоеОкноКлиентскогоПриложения"")")) > 0 Тогда
			//это работа с открытым окном
			Поз = Найти(НРег(Стр),НРег("ТестовоеПриложение.НайтиОбъект(Тип(""ТестируемоеОкноКлиентскогоПриложения"")"));
			
			ПромСтр = Сред(Стр,Поз);
			ПромСтр = СтрЗаменить(ПромСтр,"ТестовоеПриложение.НайтиОбъект(Тип(""ТестируемоеОкноКлиентскогоПриложения""),","");
			
			Поз = Найти(ПромСтр,""",");
			ПромСтр = Лев(ПромСтр,Поз);
			
			ПромСтр = СтрЗаменить(ПромСтр,"""","");
			ПромСтр = СокрЛП(ПромСтр);
			
			ИмяОкнаТестируемоеОкноКлиентскогоПриложения = ПромСтр;
			
		ИначеЕсли Найти(НРег(Стр),НРег(".НайтиОбъект(Тип(""ТестируемаяФорма"")")) > 0 Тогда
			Поз = Найти(НРег(Стр),НРег(".НайтиОбъект(Тип(""ТестируемаяФорма"")"));
			
			ПромСтр = Сред(Стр,Поз);
			ПромСтр = СтрЗаменить(ПромСтр,".НайтиОбъект(Тип(""ТестируемаяФорма""),","");
			ПромСтр = СтрЗаменить(ПромСтр,");","");
			ПромСтр = СтрЗаменить(ПромСтр,"""","");
			ПромСтр = СокрЛП(ПромСтр);
			
			ИмяТестируемойФормы = ПромСтр;
		ИначеЕсли Найти(НРег(Стр),НРег("ТаблицаСписок.Выбрать();")) > 0 Тогда
			Результат = Результат + ПолучитьПервоеКлючевоеСлово(СчетчикДействий) + " В окне """ + ИмяОкнаТестируемоеОкноКлиентскогоПриложения + """ в форме списка """ + ИмяТестируемойФормы + """ я выбираю текущий элемент." + Символы.ПС;
		ИначеЕсли Найти(НРег(Стр),НРег(".НайтиОбъект(Тип(""ТестируемоеПолеФормы"")")) > 0 Тогда
			Массив  = РазложитьСтрокуВМассивПодстрок(Стр,",");
			ПромСтр = Массив[Массив.Количество()-1];
			ПромСтр = СтрЗаменить(ПромСтр,");","");
			ПромСтр = СтрЗаменить(ПромСтр,"""","");
			ПромСтр = СокрЛП(ПромСтр);
			
			ИмяЭлементаФормы = ПромСтр;
		ИначеЕсли Найти(НРег(Стр),НРег(".ВвестиТекст(")) > 0 Тогда
			ПромСтр = Стр;
			Поз     = Найти(ПромСтр,".ВвестиТекст(");
			ПромСтр = Сред(ПромСтр,Поз);
			ПромСтр = СтрЗаменить(ПромСтр,".ВвестиТекст(","");
			ПромСтр = СтрЗаменить(ПромСтр,");","");
			ПромСтр = СтрЗаменить(ПромСтр,"""","");
			
			ЗначениеВвода = ПромСтр;
			

			Результат = Результат + ПолучитьПервоеКлючевоеСлово(СчетчикДействий) + " В открытой форме в поле """ + ИмяЭлементаФормы + """ я ввожу значение """ + ЗначениеВвода + """" + Символы.ПС;
		ИначеЕсли Найти(НРег(Стр),НРег(".ВыполнитьВыборИзСпискаВыбора(")) > 0 Тогда
			ПромСтр = Стр;
			Поз     = Найти(ПромСтр,".ВыполнитьВыборИзСпискаВыбора(");
			ПромСтр = Сред(ПромСтр,Поз);
			ПромСтр = СтрЗаменить(ПромСтр,".ВыполнитьВыборИзСпискаВыбора(","");
			ПромСтр = СтрЗаменить(ПромСтр,");","");
			ПромСтр = СтрЗаменить(ПромСтр,"""","");
			
			ЗначениеВвода = ПромСтр;
			

			Результат = Результат + ПолучитьПервоеКлючевоеСлово(СчетчикДействий) + " В открытой форме в выпадающем списке """ + ИмяЭлементаФормы + """ я ввожу значение """ + ЗначениеВвода + """" + Символы.ПС;
		ИначеЕсли Найти(НРег(Стр),НРег(".ВыполнитьВыборИзВыпадающегоСписка(")) > 0 Тогда
			Результат = Результат + ПолучитьПервоеКлючевоеСлово(СчетчикДействий) + " В открытой форме у поля """ + ИмяЭлементаФормы + """ я открываю форму выбора" + Символы.ПС;
		ИначеЕсли Найти(НРег(Стр),НРег(".НайтиОбъект(Тип(""ТестируемаяКнопкаФормы""),")) > 0 Тогда
			
			Поз = Найти(Стр,".НайтиОбъект(Тип(""ТестируемаяКнопкаФормы""),");
			ПромСтр = Сред(Стр,Поз);
			ПромСтр = СтрЗаменить(ПромСтр,".НайтиОбъект(Тип(""ТестируемаяКнопкаФормы""),","");
			
			Поз = Найти(ПромСтр,""", ");
			ПромСтр = Лев(ПромСтр,Поз);
			
			ПромСтр = СтрЗаменить(ПромСтр,");","");
			ПромСтр = СтрЗаменить(ПромСтр,"""","");
			ПромСтр = СокрЛП(ПромСтр);
			
			ИмяКнопки = ПромСтр;
			
			Результат = Результат + ПолучитьПервоеКлючевоеСлово(СчетчикДействий) + " В открытой форме я нажимаю кнопку """ + ИмяКнопки + """" + Символы.ПС;
		КонецЕсли;	 
	КонецЦикла;	
	
	Текст.Закрыть();
	Возврат Результат;
	
КонецФункции	

&НаКлиенте
Процедура ДобавитьУзел(МассивОбъектов,МассивСвойств,ИдВМассиве,Имя);
	ИдВМассиве                 = ИдВМассиве + 1;
	МассивОбъектов[ИдВМассиве] = Имя;
	МассивСвойств [ИдВМассиве] = Новый Соответствие;
КонецПроцедуры

&НаКлиенте
Процедура УдалитьУзел(МассивОбъектов,МассивСвойств,ИдВМассиве,Имя);
	МассивОбъектов[ИдВМассиве] = Неопределено;
	МассивСвойств [ИдВМассиве] = Неопределено;
	ИдВМассиве                 = ИдВМассиве - 1;
КонецПроцедуры

&НаКлиенте
Функция ОпределитьПараметрыВСтрокеПримера(Знач Стр)
	Массив = Новый Массив;
	
	Стр = СокрЛП(Стр);
	Если Лев(Стр,1) <> "|" Тогда
		Возврат Массив;
	КонецЕсли;	 
	
	Если Прав(Стр,1) <> "|" Тогда
		Возврат Массив;
	КонецЕсли;	 
	
	Стр = Сред(Стр,2);
	Стр = Сред(Стр,1,СтрДлина(Стр)-1);
	//убрали символы |
	
	Массив = РазложитьСтрокуВМассивПодстрок(Стр,"|");
	
	Для Ккк = 0 По Массив.Количество()-1 Цикл
		Массив[Ккк] = СокрЛП(Массив[Ккк]);
	КонецЦикла;
	
	Спс = Новый СписокЗначений;
	Для каждого Элем Из Массив Цикл
		Спс.Добавить(Элем);
	КонецЦикла;
	
	Возврат  Спс;
КонецФункции

&НаКлиенте
Процедура ФорматироватьСтрокиТаблицыПараметровШага(МассивТаблицы)
	МассивПараметров = ОпределитьПараметрыВСтрокеПримера(МассивТаблицы[0]);
	КолПараметров = МассивПараметров.Количество();
	МассивДлин = Новый Массив;
	Для каждого Элем Из МассивПараметров Цикл
		МассивДлин.Добавить(0);
	КонецЦикла;
	
	Для каждого СтрТзн Из МассивТаблицы Цикл
		МассивПараметров = ОпределитьПараметрыВСтрокеПримера(СтрТзн);
		
		Для Ккк = 0 По МассивДлин.Количество()-1 Цикл
			ДлинаСтроки = СтрДлина(СокрЛП(МассивПараметров.Получить(Ккк)));
			Если ДлинаСтроки > МассивДлин[Ккк] Тогда
				МассивДлин[Ккк] = ДлинаСтроки;
			КонецЕсли;	 
		КонецЦикла;
	КонецЦикла;
	
	Для Ррр = 0 по 1 Цикл
		СтрТзн = МассивТаблицы[Ррр];
		МассивПараметров = ОпределитьПараметрыВСтрокеПримера(СтрТзн);
		СтрПараметров = "| ";
		Для Ккк = 0 По МассивДлин.Количество()-1 Цикл
			Зн = СокрЛП(МассивПараметров[Ккк]);
			Пока СтрДлина(Зн) < МассивДлин[Ккк] Цикл
				Зн = Зн + " ";
			КонецЦикла;
			СтрПараметров = СтрПараметров + Зн + " | ";
		КонецЦикла;
		
		СтрПараметров = СокрЛП(СтрПараметров);
		
		МассивТаблицы[Ррр] = СтрПараметров;
	КонецЦикла;
КонецПроцедуры

&НаКлиенте
Процедура УдалитьПредыдущуюСтрокуЕслиЕстьСовпадения(Текст,Стр1,Стр2)
	СтрокаТекста = Текст.ПолучитьСтроку(Текст.КоличествоСтрок());
	
	Если Найти(СтрокаТекста,Стр1) = 0 Тогда
		Возврат;
	КонецЕсли;	 
	
	Если Найти(СтрокаТекста,Стр2) = 0 Тогда
		Возврат;
	КонецЕсли;	
	
	Текст.УдалитьСтроку(Текст.КоличествоСтрок());
КонецПроцедуры

&НаСервереБезКонтекста
Функция ПолучитьМассивДублирующихсяЗаголовоковСервер(МассивЗаголовковПолей)
	Тзн = Новый ТаблицаЗначений;
	Тзн.Колонки.Добавить("Заголовок");
	
	
	Для Н=1 По МассивЗаголовковПолей.Количество() Цикл
		Тзн.Добавить();
	КонецЦикла;	
	
	Тзн.ЗагрузитьКолонку(МассивЗаголовковПолей,"Заголовок");
	
	Тзн.Колонки.Добавить("Кол");
	
	
	
	Для каждого СтрТзн Из Тзн Цикл
		СтрТзн.Кол = 1;
	КонецЦикла;
	
	
	Тзн.Свернуть("Заголовок","Кол");
	
	Рез = Новый Массив;
	Для каждого СтрТзн Из Тзн Цикл
		Если СтрТзн.Кол > 1 Тогда
			Рез.Добавить(СтрТзн.Заголовок);
		КонецЕсли;	 
	КонецЦикла;
	
	Возврат Рез;
КонецФункции	


&НаКлиенте
Функция ПреобразоватьМассивСостояниеФормTestClient(МассивСостояниеФорм)
	
	Массив = Новый Массив;
	
	Если МассивСостояниеФорм = Неопределено Тогда
		Возврат Массив;
	КонецЕсли;	 
	
	Для каждого СостояниеФормы Из МассивСостояниеФорм Цикл
		Рез = Новый Структура;
		Рез.Вставить("ИмяФормы",СостояниеФормы.ИмяФормы);
		Рез.Вставить("ТекстЗаголовка",СостояниеФормы.ТекстЗаголовка);
		
		МассивЗаголовковПолей = СостояниеФормы.МассивЗаголовковПолей;
		МассивДублирующихсяЗаголовоковПолей = ПолучитьМассивДублирующихсяЗаголовоковСервер(МассивЗаголовковПолей);
		Рез.Вставить("МассивДублирующихсяЗаголовоковПолей",МассивДублирующихсяЗаголовоковПолей);
		
		МассивЗаголовковКнопок = СостояниеФормы.МассивЗаголовковКнопок;
		МассивДублирующихсяЗаголовоковКнопок = ПолучитьМассивДублирующихсяЗаголовоковСервер(МассивЗаголовковКнопок);
		Рез.Вставить("МассивДублирующихсяЗаголовоковКнопок",МассивДублирующихсяЗаголовоковКнопок);
		//Для каждого Элем Из МассивДублирующихсяЗаголовоковПолей Цикл
		//	Сообщить("Дубль: " + Элем);
		//КонецЦикла;
		
		Массив.Добавить(Рез);
		
	КонецЦикла;
	
	Возврат Массив;
КонецФункции	

&НаКлиенте
Функция СтрокиРавныСУчётомЗвёздочек(Знач Стр1,Знач Стр2)
	//основная строка первая
	Массив1 = РазложитьСтрокуВМассивПодстрок(Стр1," ");
	Массив2 = РазложитьСтрокуВМассивПодстрок(Стр2," ");
	
	
	Если Массив1.Количество() = (Массив2.Количество()+1) Тогда
		Если Массив1[Массив1.Количество()-1] = "*" Тогда //значит тут последний символ *
			Массив1.Удалить(Массив1.Количество()-1);
		КонецЕсли;	 
	КонецЕсли;	 
	
	Если Массив1.Количество() <> Массив2.Количество() Тогда
		Возврат Ложь;
	КонецЕсли;	 
	
	Для Ккк = 0 По Массив1.Количество()-1 Цикл
		С1 = Массив1[Ккк];
		С2 = Массив2[Ккк];
		Если С1 = С2 Тогда
			Продолжить;
		КонецЕсли;	 
		
		Если С1 = "*" Тогда
			Продолжить;
		КонецЕсли;	 
		
		Возврат Ложь;
	
	КонецЦикла;
	
	Возврат Истина;
	
КонецФункции	 

&НаКлиенте
Функция ЕстьДублиЗаголовковУПоля(МассивСтруктурФорм,ТекущаяФормаЗаголовок,ЗаголовокПоля,ТипОбъекта)
	Для каждого СтруктураФормы Из МассивСтруктурФорм Цикл
		Если СтрокиРавныСУчётомЗвёздочек(ТекущаяФормаЗаголовок,СтруктураФормы.ТекстЗаголовка) Тогда
			Если ТипОбъекта = "ПолеФормы" Тогда
				Если СтруктураФормы.МассивДублирующихсяЗаголовоковПолей.Найти(ЗаголовокПоля) <> Неопределено Тогда
					Отладка("Поле """ + ЗаголовокПоля + """ имеет дубли с таким же заголовком. Поиск будет происходить по имени.");
					Возврат Истина;
				КонецЕсли;	 
			ИначеЕсли ТипОбъекта = "Кнопка" Тогда
				Если СтруктураФормы.МассивДублирующихсяЗаголовоковКнопок.Найти(ЗаголовокПоля) <> Неопределено Тогда
					Отладка("Кнопка """ + ЗаголовокПоля + """ имеет дубли с таким же заголовком. Поиск будет происходить по имени.");
					Возврат Истина;
				КонецЕсли;	 
			КонецЕсли;	 
		КонецЕсли;	 
		//Сообщить("Сохранено: " + СтруктураФормы.ТекстЗаголовка);
	КонецЦикла;
	
	//Сообщить("Передано " + ТекущаяФормаЗаголовок);
	
	Возврат Ложь;
КонецФункции	

&НаКлиенте
Функция ПолучитьТекстФичиИзДействийПользователя(Результат)
	ИмяВременногоXML = ПолучитьИмяВременногоФайла("xml");
	
	МассивСтруктурФорм = ПреобразоватьМассивСостояниеФормTestClient(МассивСостояниеФормTestClient);
	
	
	ЗТ = Новый ЗаписьТекста(ИмяВременногоXML,"UTF-8",,Истина); 
	ЗТ.Записать(Результат); 
	ЗТ.Закрыть();
	
	ТекстРезультат = Новый ТекстовыйДокумент;
	ТекстРезультат.ДобавитьСтроку("
	|# encoding: utf-8
	|# language: ru
	|
	|Функционал: <описание фичи>
	|
	|Как <Роль>
	|Я хочу <описание функционала> 
	|Чтобы <бизнес-эффект> 
	|
	|Контекст: 
	|	Дано Я запускаю сценарий открытия TestClient или подключаю уже существующий
	|
	|
	|Сценарий: <описание сценария> 
	|");
	
	
	XML = Новый ЧтениеXML;
	XML.ОткрытьФайл(ИмяВременногоXML);
	
	МассивОбъектов = Новый Массив(100);
	МассивСвойств  = Новый Массив(МассивОбъектов.Количество());
	ИдВМассиве     = -1;
	
	СчетчикДействий      = 0;
	ТаблицаСвойствСтроки = Неопределено;
	
	ТекущееОкно  = "";
	ТекущаяФорма = "";
	ТекущаяТЧ    = "";
	Пока XML.Прочитать() Цикл
		
		ИмяУзла = XML.Имя;
		Если XML.ТипУзла = ТипУзлаXML.НачалоЭлемента Тогда
			ДобавитьУзел(МассивОбъектов,МассивСвойств,ИдВМассиве,ИмяУзла);
			Если (ИмяУзла = "gotoRow") или (ИмяУзла = "expand") или (ИмяУзла = "collapse") Тогда
				ТаблицаСвойствСтроки = Новый Массив();
			ИначеЕсли ИмяУзла = "Field" Тогда
				СвойствоСтроки = Новый Соответствие;
			КонецЕсли;	 
			Пока XML.ПрочитатьАтрибут() Цикл
				МассивСвойств[ИдВМассиве].Вставить(XML.Имя,XML.Значение);
				
				Если ИмяУзла = "Field" Тогда
					СвойствоСтроки.Вставить(XML.Имя,XML.Значение);
				КонецЕсли;	 
			КонецЦикла;
			
			Если ИмяУзла = "Form" Тогда
				ТекущаяФорма = МассивСвойств[ИдВМассиве]["title"];
			ИначеЕсли ИмяУзла = "ClientApplicationWindow" Тогда
				ТекущееОкно  = МассивСвойств[ИдВМассиве]["caption"];
			ИначеЕсли ИмяУзла = "FormTable" Тогда
				ТекущаяТЧ = МассивСвойств[ИдВМассиве]["name"];
			КонецЕсли;	 
			
			Если ИмяУзла = "click" Тогда
				Если МассивОбъектов[ИдВМассиве-1] = "CommandInterfaceButton" Тогда
					Если НРег(МассивСвойств[1]["isMain"]) = "true" Тогда
						Если МассивСвойств[ИдВМассиве-2]["title"] = "Панель разделов" Тогда
							ТекстРезультат.ДобавитьСтроку(ПолучитьПервоеКлючевоеСлово(СчетчикДействий) + " В панели разделов я выбираю """ + МассивСвойств[ИдВМассиве-1]["title"] + """");
						ИначеЕсли (МассивСвойств[ИдВМассиве-2]["title"] = "Меню функций") или (МассивСвойств[ИдВМассиве-3]["title"] = "Меню функций") Тогда
							ТекстРезультат.ДобавитьСтроку(ПолучитьПервоеКлючевоеСлово(СчетчикДействий) + " В панели функций я выбираю """ + МассивСвойств[ИдВМассиве-1]["title"] + """");
						Иначе	
							ТекстРезультат.ДобавитьСтроку(ПолучитьПервоеКлючевоеСлово(СчетчикДействий) + " Я нажимаю кнопку командного интерфейса """ + МассивСвойств[ИдВМассиве-1]["title"] + """");
						КонецЕсли;	 
					Иначе
						ТекстРезультат.ДобавитьСтроку(ПолучитьПервоеКлючевоеСлово(СчетчикДействий) + " В текущем окне я нажимаю кнопку командного интерфейса """ + МассивСвойств[ИдВМассиве-1]["title"] + """");
					КонецЕсли;	 
					
				ИначеЕсли МассивОбъектов[ИдВМассиве-1] = "FormButton" Тогда	
					ЗаголовокОбъекта = МассивСвойств[ИдВМассиве-1]["title"];
					ИмяОбъекта = """" + ЗаголовокОбъекта + """";
					Если (СокрЛП(ЗаголовокОбъекта) = "") или (ЕстьДублиЗаголовковУПоля(МассивСтруктурФорм,ТекущаяФорма,ЗаголовокОбъекта,"Кнопка")) Тогда
						ИмяОбъекта = "с именем """ + МассивСвойств[ИдВМассиве-1]["name"] + """";
					КонецЕсли;	 
					
					ДобавитьОбычнуюСтроку = Истина;
					Если ТекущаяТЧ = "" Тогда
						ДобавитьОбычнуюСтроку = Истина;
						//ТекстРезультат.ДобавитьСтроку(ПолучитьПервоеКлючевоеСлово(СчетчикДействий) + " В открытой форме я нажимаю на кнопку " + ИмяОбъекта);
					Иначе	
						//Name = МассивСвойств[ИдВМассиве-1]["name"];
						//Если Name <> Неопределено Тогда
						//	Если Лев(НРег(Name),14) = "табличнаячасть" Тогда
								ТекстРезультат.ДобавитьСтроку(ПолучитьПервоеКлючевоеСлово(СчетчикДействий) + " В открытой форме в ТЧ """ + ТекущаяТЧ + """ я нажимаю на кнопку " + ИмяОбъекта);
								ДобавитьОбычнуюСтроку = Ложь;
						//	КонецЕсли;	 
						//КонецЕсли;	 
					КонецЕсли;	
					
					Если ДобавитьОбычнуюСтроку Тогда
						ТекстРезультат.ДобавитьСтроку(ПолучитьПервоеКлючевоеСлово(СчетчикДействий) + " В открытой форме я нажимаю на кнопку " + ИмяОбъекта);
					КонецЕсли;	 
					
				ИначеЕсли (МассивОбъектов[ИдВМассиве-1] = "FormField") или (МассивОбъектов[ИдВМассиве-1] = "FormDecoration") Тогда	
					ИмяОбъекта = МассивСвойств[ИдВМассиве-1]["title"];
					Если СокрЛП(ИмяОбъекта) = "" Тогда
						ИмяОбъекта = МассивСвойств[ИдВМассиве-1]["name"];
						ТекстРезультат.ДобавитьСтроку(ПолучитьПервоеКлючевоеСлово(СчетчикДействий) + " В открытой форме я нажимаю на гиперссылку с именем """ + ИмяОбъекта + """");
					Иначе	
						ТекстРезультат.ДобавитьСтроку(ПолучитьПервоеКлючевоеСлово(СчетчикДействий) + " В открытой форме я нажимаю на гиперссылку """ + ИмяОбъекта + """");
					КонецЕсли;	 
				КонецЕсли;	 
			ИначеЕсли ИмяУзла = "close" Тогда
				ТекстРезультат.ДобавитьСтроку(ПолучитьПервоеКлючевоеСлово(СчетчикДействий) + " Я закрываю окно """ + МассивСвойств[ИдВМассиве-1]["caption"] + """");
			ИначеЕсли ИмяУзла = "choose" Тогда
				Если ТекущаяТЧ <> "" Тогда
					ТекстРезультат.ДобавитьСтроку(ПолучитьПервоеКлючевоеСлово(СчетчикДействий) + " В форме """ + ТекущаяФорма + """ в ТЧ """ + ТекущаяТЧ + """ я выбираю текущую строку");
				КонецЕсли;	 
			ИначеЕсли ИмяУзла = "startChoosing" Тогда
				Если ТекущаяТЧ <> "" Тогда
					ИмяОбъекта = МассивСвойств[ИдВМассиве-1]["title"];
					Если СокрЛП(ИмяОбъекта) = "" Тогда
						ИмяОбъекта = МассивСвойств[ИдВМассиве-1]["name"];
						ТекстРезультат.ДобавитьСтроку(ПолучитьПервоеКлючевоеСлово(СчетчикДействий) + " В открытой форме в ТЧ """ + ТекущаяТЧ + """ я нажимаю кнопку выбора у реквизита с именем """ + ИмяОбъекта + """");
					Иначе	
						ТекстРезультат.ДобавитьСтроку(ПолучитьПервоеКлючевоеСлово(СчетчикДействий) + " В открытой форме в ТЧ """ + ТекущаяТЧ + """ я нажимаю кнопку выбора у реквизита """ + ИмяОбъекта + """");
					КонецЕсли;	 
				Иначе	
					ИмяОбъекта = МассивСвойств[ИдВМассиве-1]["title"];
					Если (СокрЛП(ИмяОбъекта) <> "") и (Не ЕстьДублиЗаголовковУПоля(МассивСтруктурФорм,ТекущаяФорма,ИмяОбъекта,"ПолеФормы")) Тогда
						ТекстРезультат.ДобавитьСтроку(ПолучитьПервоеКлючевоеСлово(СчетчикДействий) + " В открытой форме я нажимаю кнопку выбора у поля """ + ИмяОбъекта + """");
					Иначе	
						ИмяОбъекта = МассивСвойств[ИдВМассиве-1]["name"];
						ТекстРезультат.ДобавитьСтроку(ПолучитьПервоеКлючевоеСлово(СчетчикДействий) + " В открытой форме я нажимаю кнопку выбора у поля с именем """ + ИмяОбъекта + """");
					КонецЕсли;	 
				КонецЕсли;	 
			ИначеЕсли ИмяУзла = "clear" Тогда
				ИмяОбъекта = МассивСвойств[ИдВМассиве-1]["title"];
				Если (СокрЛП(ИмяОбъекта) <> "") и (Не ЕстьДублиЗаголовковУПоля(МассивСтруктурФорм,ТекущаяФорма,ИмяОбъекта,"ПолеФормы")) Тогда
					ТекстРезультат.ДобавитьСтроку(ПолучитьПервоеКлючевоеСлово(СчетчикДействий) + " В открытой форме я нажимаю кнопку очистить у поля """ + ИмяОбъекта + """");
				Иначе	
					ИмяОбъекта = МассивСвойств[ИдВМассиве-1]["name"];
					ТекстРезультат.ДобавитьСтроку(ПолучитьПервоеКлючевоеСлово(СчетчикДействий) + " В открытой форме я нажимаю кнопку очистить у поля с именем """ + ИмяОбъекта + """");
				КонецЕсли;	 
			ИначеЕсли ИмяУзла = "endEditRow" Тогда
				//Если МассивОбъектов[ИдВМассиве-1] = "FormTable" Тогда
				Если ТекущаяТЧ <> "" Тогда
					Если МассивСвойств[ИдВМассиве]["cancel"] = "false" Тогда
						ТекстРезультат.ДобавитьСтроку(ПолучитьПервоеКлючевоеСлово(СчетчикДействий) + " В форме """ + ТекущаяФорма + """ в ТЧ """ + ТекущаяТЧ + """ я завершаю редактирование строки");
					КонецЕсли;	 
				КонецЕсли;	 
			ИначеЕсли ИмяУзла = "addRow" Тогда
				//Если МассивОбъектов[ИдВМассиве-1] = "FormTable" Тогда
				Если ТекущаяТЧ <> "" Тогда
					ТекстРезультат.ДобавитьСтроку(ПолучитьПервоеКлючевоеСлово(СчетчикДействий) + " В открытой форме в ТЧ """ + ТекущаяТЧ + """ я добавляю новую строку");
				КонецЕсли;	 
			ИначеЕсли ИмяУзла = "open" Тогда
				Если МассивОбъектов[ИдВМассиве-1] = "FormField" Тогда
					ИмяОбъекта = МассивСвойств[ИдВМассиве-1]["title"];
					Если СокрЛП(ИмяОбъекта) = "" Тогда
						ИмяОбъекта = МассивСвойств[ИдВМассиве-1]["name"];
						ТекстРезультат.ДобавитьСтроку(ПолучитьПервоеКлючевоеСлово(СчетчикДействий) + " В открытой форме я нажимаю на кнопку открытия поля с именем """ + ИмяОбъекта + """");
					Иначе	
						ТекстРезультат.ДобавитьСтроку(ПолучитьПервоеКлючевоеСлово(СчетчикДействий) + " В открытой форме я нажимаю на кнопку открытия поля """ + ИмяОбъекта + """");
					КонецЕсли;	 
				КонецЕсли;	 
			ИначеЕсли ИмяУзла = "openDropList" Тогда
				Если МассивОбъектов[ИдВМассиве-1] = "FormField" Тогда
					ИмяОбъекта = МассивСвойств[ИдВМассиве-1]["title"];
					Если СокрЛП(ИмяОбъекта) = "" Тогда
						ИмяОбъекта = МассивСвойств[ИдВМассиве-1]["name"];
						ТекстРезультат.ДобавитьСтроку(ПолучитьПервоеКлючевоеСлово(СчетчикДействий) + " В открытой форме я открываю выпадающий список с именем """ + ИмяОбъекта + """");
					Иначе	
						ТекстРезультат.ДобавитьСтроку(ПолучитьПервоеКлючевоеСлово(СчетчикДействий) + " В открытой форме я открываю выпадающий список """ + ИмяОбъекта + """");
					КонецЕсли;	 
				КонецЕсли;	 
			ИначеЕсли ИмяУзла = "executeChoiceFromChoiceList" Тогда
				Если МассивОбъектов[ИдВМассиве-1] = "FormField" Тогда
					Если ТекущаяТЧ <> "" Тогда
						ИмяОбъекта = МассивСвойств[ИдВМассиве-1]["title"];
						Если СокрЛП(ИмяОбъекта) = "" Тогда
							ИмяОбъекта = МассивСвойств[ИдВМассиве-1]["name"];
							ТекстРезультат.ДобавитьСтроку(ПолучитьПервоеКлючевоеСлово(СчетчикДействий) + " В открытой форме в ТЧ """ + ТекущаяТЧ + """ из выпадающего списка с именем """ + ИмяОбъекта + """ я выбираю """ + МассивСвойств[ИдВМассиве]["presentation"] + """");
						Иначе	
							ТекстРезультат.ДобавитьСтроку(ПолучитьПервоеКлючевоеСлово(СчетчикДействий) + " В открытой форме в ТЧ """ + ТекущаяТЧ + """ из выпадающего списка """ + ИмяОбъекта + """ я выбираю """ + МассивСвойств[ИдВМассиве]["presentation"] + """");
						КонецЕсли;	 
					Иначе	
						ИмяОбъекта = МассивСвойств[ИдВМассиве-1]["title"];
						Если СокрЛП(ИмяОбъекта) = "" Тогда
							ИмяОбъекта = МассивСвойств[ИдВМассиве-1]["name"];
							ТекстРезультат.ДобавитьСтроку(ПолучитьПервоеКлючевоеСлово(СчетчикДействий) + " В открытой форме из выпадающего списка с именем """ + ИмяОбъекта + """ я выбираю """ + МассивСвойств[ИдВМассиве]["presentation"] + """");
							//ТекстРезультат.ДобавитьСтроку(ПолучитьПервоеКлючевоеСлово(СчетчикДействий) + " В открытой форме в ТЧ """ + ТекущаяТЧ + """ из выпадающего списка с именем """ + ИмяОбъекта + """ я выбираю """ + МассивСвойств[ИдВМассиве]["presentation"] + """");
						Иначе	
							ТекстРезультат.ДобавитьСтроку(ПолучитьПервоеКлючевоеСлово(СчетчикДействий) + " В открытой форме из выпадающего списка """ + ИмяОбъекта + """ я выбираю """ + МассивСвойств[ИдВМассиве]["presentation"] + """");
							//ТекстРезультат.ДобавитьСтроку(ПолучитьПервоеКлючевоеСлово(СчетчикДействий) + " В открытой форме в ТЧ """ + ТекущаяТЧ + """ из выпадающего списка """ + ИмяОбъекта + """ я выбираю """ + МассивСвойств[ИдВМассиве]["presentation"] + """");
						КонецЕсли;	 
					КонецЕсли;	 
				Иначе	
					ТекстРезультат.ДобавитьСтроку(ПолучитьПервоеКлючевоеСлово(СчетчикДействий) + " В открытой форме из выпадающего списка я выбираю """ + МассивСвойств[ИдВМассиве]["presentation"] + """");
				КонецЕсли;	
				
			ИначеЕсли ИмяУзла = "executeChoiceFromDropList" Тогда
				ИмяОбъекта = МассивСвойств[ИдВМассиве-1]["title"];
				//Если МассивОбъектов[ИдВМассиве-2] = "FormTable" Тогда
				Если ТекущаяТЧ <> "" Тогда	
					Если СокрЛП(ИмяОбъекта) = "" Тогда
						ИмяОбъекта = МассивСвойств[ИдВМассиве-1]["name"];
						ТекстРезультат.ДобавитьСтроку(ПолучитьПервоеКлючевоеСлово(СчетчикДействий) + " В открытой форме в ТЧ """ + ТекущаяТЧ + """ я выбираю значение реквизита с именем """ + ИмяОбъекта + """ из формы списка");
					Иначе	
						ТекстРезультат.ДобавитьСтроку(ПолучитьПервоеКлючевоеСлово(СчетчикДействий) + " В открытой форме в ТЧ """ + ТекущаяТЧ + """ я выбираю значение реквизита """ + ИмяОбъекта + """ из формы списка");
					КонецЕсли;	 
				Иначе	
					Если СокрЛП(ИмяОбъекта) = "" Тогда
						ИмяОбъекта = МассивСвойств[ИдВМассиве-1]["name"];
						ТекстРезультат.ДобавитьСтроку(ПолучитьПервоеКлючевоеСлово(СчетчикДействий) + " В открытой форме я выбираю значение реквизита с именем """ + ИмяОбъекта + """ из формы списка");
					Иначе	
						ТекстРезультат.ДобавитьСтроку(ПолучитьПервоеКлючевоеСлово(СчетчикДействий) + " В открытой форме я выбираю значение реквизита """ + ИмяОбъекта + """ из формы списка");
					КонецЕсли;	 
				КонецЕсли;	 
			ИначеЕсли ИмяУзла = "activate" Тогда
				Если МассивОбъектов[ИдВМассиве-1] = "FormGroup" Тогда
					ИмяОбъекта = МассивСвойств[ИдВМассиве-1]["title"];
					Если СокрЛП(ИмяОбъекта) = "" Тогда
						ИмяОбъекта = МассивСвойств[ИдВМассиве-1]["name"];
						ТекстРезультат.ДобавитьСтроку(ПолучитьПервоеКлючевоеСлово(СчетчикДействий) + " В открытой форме я перехожу к закладке с именем """ + ИмяОбъекта + """");
					Иначе	
						ТекстРезультат.ДобавитьСтроку(ПолучитьПервоеКлючевоеСлово(СчетчикДействий) + " В открытой форме я перехожу к закладке """ + ИмяОбъекта + """");
					КонецЕсли;	 
					
				ИначеЕсли МассивОбъектов[ИдВМассиве-1] = "FormField" и ЗначениеЗаполнено(ТекущаяТЧ) Тогда
					//активировали колонку ТЧ
					ИмяОбъекта = МассивСвойств[ИдВМассиве-1]["title"];
					Если СокрЛП(ИмяОбъекта) = "" Тогда
						ИмяОбъекта = МассивСвойств[ИдВМассиве-1]["name"];
						ТекстРезультат.ДобавитьСтроку(ПолучитьПервоеКлючевоеСлово(СчетчикДействий) + " В открытой форме в ТЧ """ + ТекущаяТЧ + """ я активизирую поле с именем """ + ИмяОбъекта + """");
					Иначе	
						ТекстРезультат.ДобавитьСтроку(ПолучитьПервоеКлючевоеСлово(СчетчикДействий) + " В открытой форме в ТЧ """ + ТекущаяТЧ + """ я активизирую поле """ + ИмяОбъекта + """");
					КонецЕсли;	 
				КонецЕсли;	 
				
			ИначеЕсли ИмяУзла = "expand" Тогда
				Если МассивОбъектов[ИдВМассиве-1] = "FormGroup" Тогда
					ИмяОбъекта = МассивСвойств[ИдВМассиве-1]["title"];
					Если СокрЛП(ИмяОбъекта) = "" Тогда
						ИмяОбъекта = МассивСвойств[ИдВМассиве-1]["name"];
						УдалитьПредыдущуюСтрокуЕслиЕстьСовпадения(ТекстРезультат,"В открытой форме я перехожу к закладке",ИмяОбъекта);
						
						ТекстРезультат.ДобавитьСтроку(ПолучитьПервоеКлючевоеСлово(СчетчикДействий) + " В открытой форме я разворачиваю группу с именем """ + ИмяОбъекта + """");
					Иначе	
						
						
						УдалитьПредыдущуюСтрокуЕслиЕстьСовпадения(ТекстРезультат,"В открытой форме я перехожу к закладке",ИмяОбъекта);
						
						ТекстРезультат.ДобавитьСтроку(ПолучитьПервоеКлючевоеСлово(СчетчикДействий) + " В открытой форме я разворачиваю группу """ + ИмяОбъекта + """");
					КонецЕсли;	 
				КонецЕсли;	 
				
			ИначеЕсли ИмяУзла = "collapse" Тогда
				Если МассивОбъектов[ИдВМассиве-1] = "FormGroup" Тогда
					ИмяОбъекта = МассивСвойств[ИдВМассиве-1]["title"];
					Если СокрЛП(ИмяОбъекта) = "" Тогда
						ИмяОбъекта = МассивСвойств[ИдВМассиве-1]["name"];
						УдалитьПредыдущуюСтрокуЕслиЕстьСовпадения(ТекстРезультат,"В открытой форме я перехожу к закладке",ИмяОбъекта);
						
						ТекстРезультат.ДобавитьСтроку(ПолучитьПервоеКлючевоеСлово(СчетчикДействий) + " В открытой форме я сворачиваю группу с именем """ + ИмяОбъекта + """");
					Иначе	
						
						
						УдалитьПредыдущуюСтрокуЕслиЕстьСовпадения(ТекстРезультат,"В открытой форме я перехожу к закладке",ИмяОбъекта);
						
						ТекстРезультат.ДобавитьСтроку(ПолучитьПервоеКлючевоеСлово(СчетчикДействий) + " В открытой форме я сворачиваю группу """ + ИмяОбъекта + """");
					КонецЕсли;	 
				КонецЕсли;	 
				
			ИначеЕсли ИмяУзла = "goOneLevelDown" Тогда
				Если ТекущаяТЧ <> "" Тогда
					ТекстРезультат.ДобавитьСтроку(ПолучитьПервоеКлючевоеСлово(СчетчикДействий) + " В открытой форме в ТЧ  """ + ТекущаяТЧ + """ я перехожу на одну строку вниз");
				КонецЕсли;	 
			ИначеЕсли ИмяУзла = "selectOption" Тогда
				Если МассивОбъектов[ИдВМассиве-1] = "FormField" Тогда
					Если СокрЛП(МассивСвойств[ИдВМассиве-1]["title"]) <> "" Тогда
						ТекстРезультат.ДобавитьСтроку(ПолучитьПервоеКлючевоеСлово(СчетчикДействий) + " В открытой форме я меняю значение переключателя """ + МассивСвойств[ИдВМассиве-1]["title"] + """ на """ + МассивСвойств[ИдВМассиве]["presentation"] + """");
					Иначе	
						ТекстРезультат.ДобавитьСтроку(ПолучитьПервоеКлючевоеСлово(СчетчикДействий) + " В открытой форме я меняю значение переключателя с именем """ + МассивСвойств[ИдВМассиве-1]["name"] + """ на """ + МассивСвойств[ИдВМассиве]["presentation"] + """");
					КонецЕсли;	 
				КонецЕсли;	 
			ИначеЕсли ИмяУзла = "inputText" Тогда
				Если МассивОбъектов[ИдВМассиве-1] = "FormField" Тогда
					//Если МассивОбъектов[ИдВМассиве-2] = "FormTable" Тогда
					ЗаголовокПоля = МассивСвойств[ИдВМассиве-1]["title"];
					Если ТекущаяТЧ <> "" Тогда	
						Если СокрЛП(ЗаголовокПоля) <> "" Тогда
							ТекстРезультат.ДобавитьСтроку(ПолучитьПервоеКлючевоеСлово(СчетчикДействий) + " В открытой форме в ТЧ """ + ТекущаяТЧ + """ в поле """ + МассивСвойств[ИдВМассиве-1]["title"] + """ я ввожу текст """ + МассивСвойств[ИдВМассиве]["text"] + """");
						Иначе	
							ТекстРезультат.ДобавитьСтроку(ПолучитьПервоеКлючевоеСлово(СчетчикДействий) + " В открытой форме в ТЧ """ + ТекущаяТЧ + """ в поле с именем """ + МассивСвойств[ИдВМассиве-1]["name"] + """ я ввожу текст """ + МассивСвойств[ИдВМассиве]["text"] + """");
						КонецЕсли;	 
					Иначе	
						Если (СокрЛП(ЗаголовокПоля) <> "") и (Не ЕстьДублиЗаголовковУПоля(МассивСтруктурФорм,ТекущаяФорма,ЗаголовокПоля,"ПолеФормы")) Тогда
							ТекстРезультат.ДобавитьСтроку(ПолучитьПервоеКлючевоеСлово(СчетчикДействий) + " В открытой форме в поле """ + МассивСвойств[ИдВМассиве-1]["title"] + """ я ввожу текст """ + МассивСвойств[ИдВМассиве]["text"] + """");
						Иначе	
							ТекстРезультат.ДобавитьСтроку(ПолучитьПервоеКлючевоеСлово(СчетчикДействий) + " В открытой форме в поле с именем """ + МассивСвойств[ИдВМассиве-1]["name"] + """ я ввожу текст """ + МассивСвойств[ИдВМассиве]["text"] + """");
						КонецЕсли;	 
					КонецЕсли; 
				КонецЕсли;	 
			ИначеЕсли ИмяУзла = "setCheck" Тогда
				Если МассивОбъектов[ИдВМассиве-1] = "FormField" Тогда
					//Если МассивОбъектов[ИдВМассиве-2] = "FormTable" Тогда
					Если ТекущаяТЧ <> "" Тогда		
						Если СокрЛП(МассивСвойств[ИдВМассиве-1]["title"]) <> "" Тогда
							ТекстРезультат.ДобавитьСтроку(ПолучитьПервоеКлючевоеСлово(СчетчикДействий) + " В открытой форме в ТЧ """ + ТекущаяТЧ + """ я изменяю флаг """ + МассивСвойств[ИдВМассиве-1]["title"] + """");
						Иначе	
							ТекстРезультат.ДобавитьСтроку(ПолучитьПервоеКлючевоеСлово(СчетчикДействий) + " В открытой форме в ТЧ """ + ТекущаяТЧ + """ я изменяю флаг с именем """ + МассивСвойств[ИдВМассиве-1]["name"] + """");
						КонецЕсли;	 
					Иначе	
						Если СокрЛП(МассивСвойств[ИдВМассиве-1]["title"]) <> "" Тогда
							ТекстРезультат.ДобавитьСтроку(ПолучитьПервоеКлючевоеСлово(СчетчикДействий) + " В открытой форме я изменяю флаг """ + МассивСвойств[ИдВМассиве-1]["title"] + """");
						Иначе	
							ТекстРезультат.ДобавитьСтроку(ПолучитьПервоеКлючевоеСлово(СчетчикДействий) + " В открытой форме я изменяю флаг с именем """ + МассивСвойств[ИдВМассиве-1]["name"] + """");
						КонецЕсли;	 
					КонецЕсли;	 
				КонецЕсли;	 
			ИначеЕсли ИмяУзла = "ClientApplicationWindow" Тогда
				ИмяОкна = МассивСвойств[ИдВМассиве]["caption"];
				Если ИмяОкна <> Неопределено Тогда
					ТекстРезультат.ДобавитьСтроку(ПолучитьПервоеКлючевоеСлово(СчетчикДействий,"ОткрытиеОкна") + " открылось окно """ + ИмяОкна + """");
				КонецЕсли;	 
			КонецЕсли;	 
			
		КонецЕсли;
		
		Если XML.ТипУзла = ТипУзлаXML.Текст Тогда
			//Сообщить("Текст: " + XML.Значение); 
		КонецЕсли;
		
		Если XML.ТипУзла = ТипУзлаXML.КонецЭлемента Тогда 
			Если ИмяУзла = "Form" Тогда
				ТекущаяФорма = "";
			ИначеЕсли ИмяУзла = "ClientApplicationWindow" Тогда
				ТекущееОкно = "";
			ИначеЕсли ИмяУзла = "FormTable" Тогда
				ТекущаяТЧ = "";
			КонецЕсли;	 
			
			Если ИмяУзла = "gotoRow" Тогда
				Стр1 = "| ";
				Для каждого СвойствоСтроки Из ТаблицаСвойствСтроки Цикл
					Если СокрЛП(СвойствоСтроки["cellText"]) = "" Тогда
						Продолжить;
					КонецЕсли;	 
					Стр1 = Стр1 + " '" +  СвойствоСтроки["title"] + "' |";
				КонецЦикла;
				
				Стр2 = "| ";
				
				Для каждого СвойствоСтроки Из ТаблицаСвойствСтроки Цикл
					Если СокрЛП(СвойствоСтроки["cellText"]) = "" Тогда
						Продолжить;
					КонецЕсли;	 
					Стр2 = Стр2 + " '" + СвойствоСтроки["cellText"] + "' |";
				КонецЦикла;
				
				//Стр1 = СтрЗаменить(Стр1,"""","&quot;");
				//Стр2 = СтрЗаменить(Стр2,"""","&quot;");
				
				МассивТаблицы = Новый Массив();
				МассивТаблицы.Добавить(Стр1);
				МассивТаблицы.Добавить(Стр2);
				
				ФорматироватьСтрокиТаблицыПараметровШага(МассивТаблицы);
				
				Стр = "	" + МассивТаблицы[0] + Символы.ПС + "	" + МассивТаблицы[1];
				
				
				Если ТаблицаСвойствСтроки.Количество() > 0 Тогда
					//ТекстРезультат.ДобавитьСтроку(ПолучитьПервоеКлючевоеСлово(СчетчикДействий) + " В форме """ + МассивСвойств[ИдВМассиве-2]["title"] + """ в таблице """ + МассивСвойств[ИдВМассиве-1]["title"] +  """ я перехожу к строке """ + Стр + """");
					ТекстРезультат.ДобавитьСтроку(ПолучитьПервоеКлючевоеСлово(СчетчикДействий) + " В форме """ + ТекущаяФорма + """ в таблице """ + МассивСвойств[ИдВМассиве-1]["name"] +  """ я перехожу к строке:");
					ТекстРезультат.ДобавитьСтроку(Стр);
				КонецЕсли;	 
				
			ИначеЕсли ИмяУзла = "Field" Тогда
				ТаблицаСвойствСтроки.Добавить(СвойствоСтроки);
			КонецЕсли;	 
			
			
			УдалитьУзел(МассивОбъектов,МассивСвойств,ИдВМассиве,XML.Имя);
			//Сообщить("КонецЭлемента.");
		КонецЕсли; 
	КонецЦикла; 
	XML.Закрыть();
	СгенерированныйСценарий = ТекстРезультат.ПолучитьТекст();
	
КонецФункции	

&НаКлиенте
Процедура ЗавершитьЗаписьДействийПользователя() Экспорт
	ОтключитьОбработчикОжидания("ОпросЭлементовФормTestClient");
	Попытка
		Стр = ОбъектКонтекстСохраняемый.ТестовоеПриложение.ЗавершитьЗаписьЖурналаДействийПользователя();
		СделатьСообщение("Запись действий пользователя закончена.");
	Исключение
		Сообщить("" + ОписаниеОшибки());
		Возврат;
	КонецПопытки;
	
	Текст = Новый ТекстовыйДокумент;
	Текст.ДобавитьСтроку(Стр);
	
	СгенерированныйXML = Текст.ПолучитьТекст();
	
	Попытка
		ПутьКОбработке = ДополнитьСлешВПуть(Объект.КаталогИнструментов) + "vendor/1C/UILogToScript.epf";
		ДвоичныеДанные = Новый ДвоичныеДанные(ПутьКОбработке);
		Результат = ПолучитьКод1СИзUILogToScriptСервер(ДвоичныеДанные,Стр);
		
		ОбработатьПолученныйКодUILogToScript(Результат);
		
		Текст = Новый ТекстовыйДокумент;
		Текст.ДобавитьСтроку(Результат);
		
		СгенерированныйКод = Текст.ПолучитьТекст();
		
	Исключение
		Сообщить("Не смог обработать XML в UILogToScript.");
		Сообщить("" + ОписаниеОшибки());
	КонецПопытки;
	
	Попытка
		ПолучитьТекстФичиИзДействийПользователя(Стр);
	Исключение
		Сообщить("Ошибка при получении текста фичи:");
		Сообщить("" + ОписаниеОшибки());
	КонецПопытки;
КонецПроцедуры


&НаКлиенте
Процедура ЗавершитьЗаписьДействийПользователяКнопка(Команда)
	ЗавершитьЗаписьДействийПользователя();
КонецПроцедуры

&НаКлиенте
Процедура КаталогФичНажатие(Элемент, СтандартнаяОбработка)
	Сообщить("" + Объект.КаталогФич);
	СтандартнаяОбработка = Ложь;
КонецПроцедуры

&НаКлиенте
Функция ПодключитьУжеЗапущенныйTestClient()
	Если ТипЗнч(ОбъектКонтекстСохраняемый) <> Тип("Структура") Тогда
		Возврат Ложь;
	КонецЕсли;	
	
	Если НЕ ОбъектКонтекстСохраняемый.Свойство("ТестовоеПриложение") Тогда
		Попытка
			ТестовоеПриложение = СоздатьТестовоеПриложение();
			ТестовоеПриложение.УстановитьСоединение();
			ЗаполнитьКонтекстСохраняемыйДляТестовоеПриложение(ТестовоеПриложение);
			
			Возврат Истина;
		Исключение
			Возврат Ложь;		
		КонецПопытки;
		
		Возврат Ложь;
	КонецЕсли;	 
	
	ТестовоеПриложение = ОбъектКонтекстСохраняемый.ТестовоеПриложение;
	
	Если ТестовоеПриложение = Неопределено Тогда
		Возврат Ложь;
	КонецЕсли;	 
	
	Попытка
		ТестовоеПриложение.УстановитьСоединение();
		ГлавноеОкноТестируемого = ПолучитьГлавноеОкноТестируемого(ТестовоеПриложение);
		Если ГлавноеОкноТестируемого = Неопределено Тогда
			//ВызватьИсключение "Не смог найти ГлавноеОкноТестируемого у уже подключенного TestClient.";
			Возврат Ложь;
		КонецЕсли;	 
		ЗаполнитьКонтекстСохраняемыйДляТестовоеПриложение(ТестовоеПриложение);
	Исключение
		Возврат Ложь;
	КонецПопытки;
	
	Возврат Истина;
КонецФункции	

&НаКлиенте
Процедура ЗапуститьСеансTestClient(ДопПараметр = "")
	СисИнфо = Новый СистемнаяИнформация; 
	ВерсияПриложения = СисИнфо.ВерсияПриложения;
	
	//ПутьК1С = "C:\Program Files (x86)\1cv8\" + ВерсияПриложения + "\bin\1cv8.exe";
	//ФайлПроверкаСуществования = Новый Файл(ПутьК1С);
	
	КаталогБазы = СтрокаСоединенияИнформационнойБазы();
	Если Найти(ВРег(КаталогБазы),ВРег("File=")) > 0 Тогда
		КаталогБазы = СтрЗаменить(КаталогБазы,"File="," /F");
	Иначе
		КаталогБазы = СтрЗаменить(КаталогБазы,"Srvr=","/S");
		КаталогБазы = СтрЗаменить(КаталогБазы,""";Ref=""","\");
	КонецЕсли;
	КаталогБазы = СтрЗаменить(КаталогБазы,";","");
	
	СтрокаЗапуска1с = КаталогПрограммы() + "1cv8c";
	Если ЭтоLinux = Ложь Тогда
		СтрокаЗапуска1с = СтрокаЗапуска1с + ".exe";
	Иначе
		КаталогБазы = СтрЗаменить(КаталогБазы, "\", "/");
	КонецЕсли;
		
	СтрокаЗапуска = """" + СтрокаЗапуска1с + """ ENTERPRISE " + КаталогБазы;
	
	Если ЭтоЗапускВРежимеКоманднойСтроки Тогда
		СтрокаЗапуска = СтрокаЗапуска + " /TESTCLIENT /CTemp " + ДопПараметр;//добавил /CTemp, чтобы убрать передачу параметра в TestClient, с которым был запущен TestManager
	Иначе
		СтрокаЗапуска = СтрокаЗапуска + " /TESTCLIENT " + ДопПараметр;	
	КонецЕсли;	 
	
	//Сообщить("СтрокаЗапуска="+СтрокаЗапуска);
	
	ЗапуститьСистему(СтрокаЗапуска);
	
КонецПроцедуры


&НаКлиенте
Процедура ЗавершитьСеансыTestClientПринудительно() Экспорт
	ИмяВременногоФайла = ПолучитьИмяВременногоФайла("txt");
	
	Если НЕ ЭтоLinux Тогда 
		ИмяВременногоBat = ПолучитьИмяВременногоФайла("bat");
		ЗТ = Новый ЗаписьТекста(ИмяВременногоBat,"windows-1251",,Истина); 
		ЗТ.ЗаписатьСтроку("chcp 65001"); 
		ЗТ.ЗаписатьСтроку("tasklist /v /fo list /fi ""imagename eq 1cv8c.exe"" > " + ИмяВременногоФайла); 
		ЗТ.Закрыть();
		
		ЗапуститьПриложение(ИмяВременногоBat,,Истина);
		
		Текст = Новый ЧтениеТекста;
		Текст.Открыть(ИмяВременногоФайла,"UTF-8");
		
		МассивProcessID = Новый Массив;
		ProcessID = Неопределено;
		Пока Истина Цикл
			Стр = Текст.ПрочитатьСтроку();
			Если Стр = Неопределено Тогда
				Прервать;
			КонецЕсли;	 
			
			Стр = НРег(Стр);
			Если Лев(Стр,4) = "pid:" Тогда
				ProcessID = СокрЛП(Сред(Стр,5));
			КонецЕсли;	 
			
			Если ProcessID <> Неопределено Тогда
				Если (Лев(Стр,15) = "заголовок окна:") или (Лев(Стр,13) = "window title:") Тогда
					Если Найти(Стр,"vanessa") = 0 Тогда
						МассивProcessID.Добавить(ProcessID);
					КонецЕсли;	 
				КонецЕсли;	 
			КонецЕсли;	 
		КонецЦикла;	
		Текст.Закрыть();
		
		Если МассивProcessID.Количество() = 0 Тогда
			Возврат;
		КонецЕсли;	 
		
		ИмяВременногоBat = ПолучитьИмяВременногоФайла("bat");
		ЗТ = Новый ЗаписьТекста(ИмяВременногоBat,"UTF-8",,Истина); 
		Стр = "taskkill /F ";
		Для каждого ProcessID Из МассивProcessID Цикл
			Стр = Стр + "/pid " + ProcessID + " ";
		КонецЦикла;
		ЗТ.ЗаписатьСтроку(Стр); 
		ЗТ.Закрыть();
		
		ЗапуститьПриложение(ИмяВременногоBat,,Истина);
		
	Иначе 
		
		СтрокаЗапуска = "kill -9 `ps aux | grep -ie TESTCLIENT | grep -ie 1cv8c | awk '{print $2}'`";
		ЗапуститьПриложение(СтрокаЗапуска);
		
	КонецЕсли;
	
КонецПроцедуры

&НаКлиенте
Функция СоздатьТестовоеПриложение()
	ТипЗначения = Тип("ТестируемоеПриложение");
	ПараметрыОбъекта = Новый Массив;
	ПараметрыОбъекта.Добавить("localhost");
	ТестовоеПриложение = Новый (ТипЗначения,ПараметрыОбъекта);
	
	Возврат ТестовоеПриложение;
КонецФункции	

&НаКлиенте
Процедура УстановитьКонектСTestClient(ТестовоеПриложение)
	Если ТипЗнч(ОбъектКонтекстСохраняемый) <> Тип("Структура") Тогда
		ОбъектКонтекстСохраняемый = Новый Структура;
	КонецЕсли;	 
	
	ОбъектКонтекстСохраняемый.Вставить("ТестовоеПриложение",ТестовоеПриложение);
	
	Попытка
		ТестовоеПриложение.УстановитьСоединение();
		ГлавноеОкноТестируемого = Неопределено;
		ГлавноеОкноТестируемого = ПолучитьГлавноеОкноТестируемого(ТестовоеПриложение);
		//ГлавноеОкноТестируемого.Активизировать();
	Исключение
		СделатьСообщение("Делаю перезапуск TESTCLIENT.");
		Отладка("ОписаниеОшибки=" + ОписаниеОшибки());
		ЗавершитьСеансыTestClientПринудительно();
		ЗапуститьСеансTestClient();
		
		ТестовоеПриложение      = ОбъектКонтекстСохраняемый.ТестовоеПриложение;
	КонецПопытки;
	
	ЗаполнитьКонтекстСохраняемыйДляТестовоеПриложение(ТестовоеПриложение);
	
КонецПроцедуры

&НаКлиенте
Функция ПолучитьГлавноеОкноТестируемого(ТестовоеПриложение)
	ГлавноеОкноТестируемого = Неопределено;
	КлиентсткиеОкнаТестируемогоПриложения = ТестовоеПриложение.ПолучитьПодчиненныеОбъекты();
	Для Каждого ТестируемоеОкно Из КлиентсткиеОкнаТестируемогоПриложения Цикл
		Если ТестируемоеОкно.Основное Тогда
			ГлавноеОкноТестируемого = ТестируемоеОкно;
			Прервать;
		КонецЕсли;
	КонецЦикла;
	
	Возврат ГлавноеОкноТестируемого;
КонецФункции	

&НаКлиенте
Процедура ЗаполнитьКонтекстСохраняемыйДляТестовоеПриложение(ТестовоеПриложение)
	ОбъектКонтекстСохраняемый.Вставить("ТестовоеПриложение",ТестовоеПриложение);
	ГлавноеОкноТестируемого = ПолучитьГлавноеОкноТестируемого(ТестовоеПриложение);
	ОбъектКонтекстСохраняемый.Вставить("ГлавноеОкноТестируемого",ГлавноеОкноТестируемого);
КонецПроцедуры

&НаКлиенте
Функция ОткрытьНовыйСеансTestClientИлиПодключитьУжеСуществующий(ДопПараметр = "") Экспорт 
	//УстановитьКраткийЗаголовокПриложения("Vanessa-behavior");
	
	Если ПодключитьУжеЗапущенныйTestClient() Тогда
		СделатьСообщение("TestClient подключен.");
		Возврат Истина;
	КонецЕсли;	
	
	Попытка
		ТестовоеПриложение = СоздатьТестовоеПриложение();
	Исключение
		СделатьСообщение("Сеанс должен быть запущен с ключом TESTMANAGER!");
		СделатьСообщение("TestClient НЕ подключен.");
	    Возврат Ложь;
	КонецПопытки;
	
	Попытка
		ЗапуститьСеансTestClient(ДопПараметр);
		Sleep(4);
		УстановитьКонектСTestClient(ТестовоеПриложение);
		СделатьСообщение("TestClient подключен.");
	Исключение
		СделатьСообщение("TestClient НЕ подключен.");
	    Возврат Ложь;
	КонецПопытки;
	
	Возврат Истина;
КонецФункции

&НаКлиенте
Процедура ОткрытьПодключитьTestClient(Команда) Экспорт
	ОткрытьНовыйСеансTestClientИлиПодключитьУжеСуществующий();
КонецПроцедуры

&НаКлиенте
Процедура РазвернутьСтрокуДерева(Строка)
	ИдентификаторСтроки=Строка.ПолучитьИдентификатор();
	Если Строка.Область = Истина Тогда
		Элементы.ДеревоТестов.Свернуть(ИдентификаторСтроки);
		Возврат;
	КонецЕсли;	 
	
	ИдентификаторСтроки=Строка.ПолучитьИдентификатор();
	Элементы.ДеревоТестов.Развернуть(ИдентификаторСтроки);
КонецПроцедуры

&НаКлиенте
Процедура СвернутьСтрокуДерева(Строка)
	ИдентификаторСтроки=Строка.ПолучитьИдентификатор();
	Элементы.ДеревоТестов.Свернуть(ИдентификаторСтроки);
КонецПроцедуры

&НаКлиенте
Процедура РазвернутьСтрокиДерева(ДеревоФормыСтроки)
	Для Каждого Строка Из ДеревоФормыСтроки Цикл
		РазвернутьСтрокуДерева(Строка);
		
		Если Строка.Область = Истина Тогда
			Продолжить;
		КонецЕсли;	 
		
		ПодчиненныеСтроки = Строка.ПолучитьЭлементы();
		Если ПодчиненныеСтроки.Количество() > 0 Тогда
			РазвернутьСтрокиДерева(ПодчиненныеСтроки);
		КонецЕсли;	 
		
		//ИдентификаторСтроки=Строка.ПолучитьИдентификатор();
		//Элементы.ДеревоТестов.Развернуть(ИдентификаторСтроки, Истина);
	КонецЦикла;
КонецПроцедуры

&НаКлиенте
Процедура РазвернутьДерево() Экспорт
	ДеревоФормыСтроки = Объект.ДеревоТестов.ПолучитьЭлементы();
	РазвернутьСтрокиДерева(ДеревоФормыСтроки);
КонецПроцедуры

&НаСервере
Функция СформироватьОтчетВоВнутреннемФормате(СтруктураОФ) 
	
	ОбъектСервер = РеквизитФормыВЗначение("Объект");
	Дерево = ОбъектСервер.ДеревоТестов;
	
	Возврат ОбъектСервер.ВывестиОтчетТестированияВоВнутреннемФормате(Дерево, СтруктураОФ);
		
КонецФункции

&наКлиенте
Процедура ДобавитьВнешнийСписокПроцедур(МассивСнипетовИзОбработки, ПолноеИмя, ФормаОбработки) Экспорт 
	
	СтрТаблицаКонтекстовОбработок = Новый Структура;
	СтрТаблицаКонтекстовОбработок.Вставить("ИмяФайла",ПолноеИмя);
	СтрТаблицаКонтекстовОбработок.Вставить("Обработка",ФормаОбработки);
	ТаблицаКонтекстовОбработок.Добавить(СтрТаблицаКонтекстовОбработок);
		
	МассивИменКонтекстовОбработок.Добавить(ПолноеИмя);
	БылиОшибки = Ложь;
	Для каждого Снипет из МассивСнипетовИзОбработки Цикл 
		ТаблицаОбработокДляОтладки.Вставить(СокрЛП(Снипет.ИмяПроцедуры), Новый Структура("ИмяПроцедуры, Обработка, ИмяФайла", Снипет.ИмяПроцедуры, ФормаОбработки, ПолноеИмя));
	КонецЦикла;
	
КонецПроцедуры

&НаКлиенте
Процедура ПодключитьВнешниеОбработкиДляОтладки() 
	Перем МассивФорм;
	МассивФорм = Новый Массив;
	
	ФормаVanessa = Неопределено;
	
	Окна = ПолучитьОкна();
	Для каждого Окн Из Окна Цикл
		Если ТипЗнч(Окн) = Тип("ОкноКлиентскогоПриложения") Тогда
			Если Найти(НРег(Строка(Окн.Заголовок)), "тест_")>0 ИЛИ 
				Найти(НРег(Строка(Окн.Заголовок)), "test_")>0 Тогда
				
				МассивФорм.Добавить(Окн.ПолучитьСодержимое());
				
			КонецЕсли;
		КонецЕсли;
		
	КонецЦикла;
	
	Если МассивФорм.Количество() > 0 Тогда
		
		Для каждого Форма Из МассивФорм Цикл
			Попытка
				ДобавитьВнешнийСписокПроцедур(Форма.ПолучитьСписокТестов(ЭтаФорма), Форма.УникальныйИдентификатор, Форма);
				Сообщить("Подключили для отладки форма "+Форма.Заголовок);
			Исключение
				Сообщить("Не удалось подключить форма "+Форма.Заголовок + " по причине:" + ОписаниеОшибки());
			    //ОписаниеОшибки()
			КонецПопытки; 
		КонецЦикла; 
	КонецЕсли;
	
КонецПроцедуры

&НаКлиенте
Функция МетаданныеИмя() Экспорт
	Возврат МетаданныеИмяСервер();
КонецФункции

&НаСервере
Функция МетаданныеИмяСервер()
	ОсновнойОбъект = Объект();
	НайденноеИмя = ОсновнойОбъект.Метаданные().Имя;
	
	Возврат НайденноеИмя;
КонецФункции

&НаКлиенте
Процедура ДеревоТестовПриАктивизацииСтроки(Элемент)
	
	Возврат;
	
	
	
	
	
	Если ВсёЕщёИдётВыполнениеШагов > 0 Тогда
		Возврат;
	КонецЕсли;	 
	
	ТекущиеДанные = Элементы.ДеревоТестов.ТекущиеДанные;
	
	
	Если ТекущиеДанные = Неопределено Тогда
		Возврат;
	КонецЕсли;	 
	
	Если НЕ Элементы.ДеревоТестовКонтекстноеМенюПунктВыполнитьСценарий.Видимость Тогда
		Элементы.ДеревоТестовКонтекстноеМенюПунктВыполнитьСценарий.Видимость = Истина;
	КонецЕсли;	 
	
	Если НЕ Элементы.ДеревоТестовКонтекстноеМенюПунктОткрытьФичаФайл.Видимость Тогда
		Элементы.ДеревоТестовКонтекстноеМенюПунктОткрытьФичаФайл.Видимость   = Истина;
	КонецЕсли;	 
	
	Если Элементы.ДеревоТестовКонтекстноеМенюВыполнятьСценарийСЭтогоШага.Видимость Тогда
		Элементы.ДеревоТестовКонтекстноеМенюВыполнятьСценарийСЭтогоШага.Видимость   = Ложь;
	КонецЕсли;	 
	
	
	
	
	
	
	
	
	Если Объект.РежимВыполненияСценарияСВыбранногоШага <> Элементы.ДеревоТестовКонтекстноеМенюВыполнятьСценарииСначала.Видимость Тогда
		Элементы.ДеревоТестовКонтекстноеМенюВыполнятьСценарииСначала.Видимость = Объект.РежимВыполненияСценарияСВыбранногоШага;
	КонецЕсли;	 
	
	
	Если ТекущиеДанные.Фича = Истина Тогда
		Если Элементы.ДеревоТестовКонтекстноеМенюПунктВыполнитьСценарий.Видимость Тогда
			Элементы.ДеревоТестовКонтекстноеМенюПунктВыполнитьСценарий.Видимость = Ложь;
		КонецЕсли;	 
		
	ИначеЕсли ТекущиеДанные.Сценарий = Истина Тогда
		
	ИначеЕсли ТекущиеДанные.Шаг = Истина Тогда
		Если НЕ Элементы.ДеревоТестовКонтекстноеМенюВыполнятьСценарийСЭтогоШага.Видимость Тогда
			Элементы.ДеревоТестовКонтекстноеМенюВыполнятьСценарийСЭтогоШага.Видимость = Истина;
		КонецЕсли;	 
		
		
	Иначе	
		Если Элементы.ДеревоТестовКонтекстноеМенюПунктВыполнитьСценарий.Видимость Тогда
			Элементы.ДеревоТестовКонтекстноеМенюПунктВыполнитьСценарий.Видимость = Ложь;
		КонецЕсли;	 
		Если Элементы.ДеревоТестовКонтекстноеМенюПунктОткрытьФичаФайл.Видимость Тогда
			Элементы.ДеревоТестовКонтекстноеМенюПунктОткрытьФичаФайл.Видимость   = Ложь;
		КонецЕсли;	 
	КонецЕсли;	 
КонецПроцедуры


&НаКлиенте
Процедура АктивироватьСоседнююСтрокуДерева(СтрокаДерва)
	СтрокаРодитель = СтрокаДерва.ПолучитьРодителя();
	Если СтрокаРодитель = Неопределено Тогда
		Возврат;
	КонецЕсли;	 
	СтрокиДерева   = СтрокаРодитель.ПолучитьЭлементы();
	Для Ккк = 0 По СтрокиДерева.Количество()-1 Цикл
		ТекСтрока = СтрокиДерева[Ккк];
		
		Если ТекСтрока = СтрокаШагаСКоторогоНадоВыполнятьСценарий Тогда
			Если Ккк < СтрокиДерева.Количество()-1 Тогда
				НужнаяСтрока = СтрокиДерева[Ккк+1];
			ИначеЕсли Ккк > 0 Тогда	
				НужнаяСтрока = СтрокиДерева[Ккк-1];
			Иначе
				Продолжить;
			КонецЕсли;	 
			
			Элементы.ДеревоТестов.ТекущаяСтрока = НужнаяСтрока.ПолучитьИдентификатор();
			
			Прервать;
		КонецЕсли;	 
	КонецЦикла;
КонецПроцедуры

&НаКлиенте
Процедура ПроцУстановитьПометкуВыполнятьСценарийСЭтогоШага() Экспорт
	ТекущиеДанные = Элементы.ДеревоТестов.ТекущиеДанные;
	Если ТекущиеДанные = Неопределено Тогда
		Возврат;
	КонецЕсли;	 
	
	Если ТекущиеДанные.Шаг <> Истина Тогда
		Сообщить("Это возможно только для шага.");
		Возврат;
	КонецЕсли;	
	
	Если СтрокаШагаСКоторогоНадоВыполнятьСценарий <> Неопределено Тогда
		Если СтрокаШагаСКоторогоНадоВыполнятьСценарий.Шаг = Истина Тогда
			ПромСтрока = Неопределено;
			НайтиСтрокуДереваПоИдСтроки(СтрокаШагаСКоторогоНадоВыполнятьСценарий.ИдСтроки,Объект.ДеревоТестов.ПолучитьЭлементы(),ПромСтрока);
			СтрокаШагаСКоторогоНадоВыполнятьСценарий = ПромСтрока;
			
			СтрокаШагаСКоторогоНадоВыполнятьСценарий.ВыполнятьСценарийСЭтогоШага = Ложь;	
		КонецЕсли;	 
	КонецЕсли;	 
	
	СтрокаШагаСКоторогоНадоВыполнятьСценарий  = ТекущиеДанные;
	ТекущиеДанные.ВыполнятьСценарийСЭтогоШага = Истина;	
	
	АктивироватьСоседнююСтрокуДерева(СтрокаШагаСКоторогоНадоВыполнятьСценарий);
	//ОбъектКонтекстДляВыполненияСВыбранногоШага            = Неопределено;
	//ОбъектКонтекстДляВыполненияСВыбранногоШагаСохраняемый = Неопределено;
	
	Объект.РежимВыполненияСценарияСВыбранногоШага = Истина;
	Объект.СохранятьКонтекстыПередВыполнениемШагов = Истина;
	
	
	Элементы.ДеревоТестовКонтекстноеМенюВыполнятьСценарииСначала.Видимость   = Истина;
	
	Сообщить("Пометка установлена!");
КонецПроцедуры

&НаКлиенте
Процедура УстановитьПометкуВыполнятьСценарийСЭтогоШага(Команда)
	ПроцУстановитьПометкуВыполнятьСценарийСЭтогоШага();
КонецПроцедуры

&НаКлиенте
Процедура НайтиСтрокуДереваПоИдСтроки(ИдСтроки,СтрокиДерева,Результат)
	
	Для каждого СтрокаДерева Из СтрокиДерева Цикл
		Если Результат <> Неопределено Тогда
			Возврат;
		КонецЕсли;	 
		
		
		Если ИдСтроки = СтрокаДерева.ИдСтроки Тогда
			Результат = СтрокаДерева;
			Возврат;
		КонецЕсли;	 
		
		ПодчиненныеЭлементыСтроки = СтрокаДерева.ПолучитьЭлементы();
		НайтиСтрокуДереваПоИдСтроки(ИдСтроки,ПодчиненныеЭлементыСтроки,Результат);
	КонецЦикла;
КонецПроцедуры	

&НаКлиенте
Процедура СнятьПометкуВыполнятьСценарийСЭтогоШага(Команда)
	Объект.РежимВыполненияСценарияСВыбранногоШага = Ложь;
	Если СтрокаШагаСКоторогоНадоВыполнятьСценарий <> Неопределено Тогда
		ПромСтрока = Неопределено;
		НайтиСтрокуДереваПоИдСтроки(СтрокаШагаСКоторогоНадоВыполнятьСценарий.ИдСтроки,Объект.ДеревоТестов.ПолучитьЭлементы(),ПромСтрока);
		СтрокаШагаСКоторогоНадоВыполнятьСценарий = ПромСтрока;
		
		СтрокаШагаСКоторогоНадоВыполнятьСценарий.ВыполнятьСценарийСЭтогоШага = Ложь;
	КонецЕсли;	 
	
	СтрокаШагаСКоторогоНадоВыполнятьСценарий = Неопределено;
	
	Элементы.ДеревоТестовКонтекстноеМенюВыполнятьСценарииСначала.Видимость = Ложь;
	
	Сообщить("Пометка снята!");
КонецПроцедуры

&НаКлиенте
Функция ЭтоПустаяСтрокаТабличногоДокумента(СтрокаТабДок)
	Для каждого Зн Из СтрокаТабДок Цикл
		Если Зн <> "" Тогда
			Возврат Ложь;
		КонецЕсли;	 
	КонецЦикла;
	
	Возврат Истина;
КонецФункции	

&НаКлиенте
Процедура УбратьПустыеСтрокиИКолонкиСКраёвМакета(ТабДок)
	Если ТабДок.Количество() = 0 Тогда
		Возврат;
	КонецЕсли;	
	Если ТабДок[0].Количество() = 0 Тогда
		Возврат;
	КонецЕсли;	
	
	
	
	
	
	
	//пустые строки сверху
	МассивСтрокДляУдаления = Новый Массив;
	Ном = -1;
	Для каждого СтрокаТабДок Из ТабДок Цикл
		Ном = Ном + 1;
		Если ЭтоПустаяСтрокаТабличногоДокумента(СтрокаТабДок) Тогда
			МассивСтрокДляУдаления.Добавить(Ном);
		Иначе
			//значит нашли первую не пустую строку
			Прервать;
		КонецЕсли;	 
	КонецЦикла;
	
	
	Для Ккк = 0 По МассивСтрокДляУдаления.Количество()-1 Цикл
		ИдМассива = МассивСтрокДляУдаления[МассивСтрокДляУдаления.Количество()-1 - Ккк];
		ТабДок.Удалить(ИдМассива);
	КонецЦикла;
	
	
	
	//пустые строки снизу
	МассивСтрокДляУдаления = Новый Массив;
	Для Ккк = 0 По ТабДок.Количество()-1 Цикл
		Ном          = ТабДок.Количество()-1-Ккк;
		СтрокаТабДок = ТабДок[Ном];
		Если ЭтоПустаяСтрокаТабличногоДокумента(СтрокаТабДок) Тогда
			МассивСтрокДляУдаления.Добавить(Ном);
		Иначе
			//значит нашли первую не пустую строку
			Прервать;
		КонецЕсли;	 
	КонецЦикла;

	
	Для каждого ИдМассива Из МассивСтрокДляУдаления Цикл
	    ТабДок.Удалить(ИдМассива);
	КонецЦикла;
	
	
	
	
	Если ТабДок.Количество() = 0 Тогда
		Возврат;
	КонецЕсли;	 
	
	
	//пустые колонки слева
	КолКолонок = ТабДок[0].Количество();
	МассивКолонокДляУдаления = Новый Массив;
	Ном = -1;
	Для ИдКолонки = 0 По КолКолонок-1 Цикл
		КолонкаПустая = Истина;
		Для каждого СтрокаТабДок Из ТабДок Цикл
			Зн = СтрокаТабДок[ИдКолонки];
			Если Зн <> "" Тогда
				КолонкаПустая = Ложь;
				Прервать;
			КонецЕсли;	 
		КонецЦикла;
		
		Если КолонкаПустая Тогда
			МассивКолонокДляУдаления.Добавить(ИдКолонки);
		Иначе
			Прервать;
		КонецЕсли;	 
		
	КонецЦикла;
	
	
	Для Ккк = 0 По МассивКолонокДляУдаления.Количество()-1 Цикл
		ИдМассива = МассивКолонокДляУдаления[МассивКолонокДляУдаления.Количество()-1 - Ккк];
		Для каждого СтрокаТабДок Из ТабДок Цикл
			СтрокаТабДок.Удалить(ИдМассива);
		КонецЦикла;
	КонецЦикла;
	
	
	
	
	
	
	//пустые колонки справа
	КолКолонок = ТабДок[0].Количество();	
	МассивКолонокДляУдаления = Новый Массив;
	Ном = -1;
	Для Ккк = 0 По КолКолонок-1 Цикл
		ИдКолонки = КолКолонок-1 - Ккк;
		
		
		КолонкаПустая = Истина;
		Для каждого СтрокаТабДок Из ТабДок Цикл
			Зн = СтрокаТабДок[ИдКолонки];
			Если Зн <> "" Тогда
				КолонкаПустая = Ложь;
				Прервать;
			КонецЕсли;	 
		КонецЦикла;
		
		Если КолонкаПустая Тогда
			МассивКолонокДляУдаления.Добавить(ИдКолонки);
		Иначе
			Прервать;
		КонецЕсли;	 
		
	КонецЦикла;
	
	
	Для Ккк = 0 По МассивКолонокДляУдаления.Количество()-1 Цикл
		ИдМассива = МассивКолонокДляУдаления[Ккк];
		Для каждого СтрокаТабДок Из ТабДок Цикл
			СтрокаТабДок.Удалить(ИдМассива);
		КонецЦикла;
	КонецЦикла;
	
	
	
КонецПроцедуры

&НаКлиенте
Функция ПолучитьТабДокИзTestClient(ЭлементФормы) Экспорт
	ТабДок = Новый Массив();
	Для Стр = СчитываниеМакетаНачСтр По СчитываниеМакетаНачСтр + СчитываниеМакетаКолСтр - 1 Цикл
		СтрокаТабДок = Новый Массив;
		Для Кол = СчитываниеМакетаНачКол По СчитываниеМакетаНачКол + СчитываниеМакетаКолКол - 1 Цикл
			Адрес = "R" + Стр + "C" + Кол;
			Адрес = СтрЗаменить(Адрес,Символы.НПП,"");
			
			Значение = ЭлементФормы.ПолучитьТекстОбласти(Адрес);
			Значение = СтрЗаменить(Значение,Символы.ПС,"\n");
			
			СтрокаТабДок.Добавить(Значение);
		КонецЦикла;
		
		ТабДок.Добавить(СтрокаТабДок);
	КонецЦикла;
	УбратьПустыеСтрокиИКолонкиСКраёвМакета(ТабДок);
	
	Возврат ТабДок;
КонецФункции	

&НаКлиенте
Функция ПолучитьЗначениеТестируемаяТаблицаФормы(ЭлементФормы)
	НадоПолучатьСтроки = Истина;
	ЗначениеТЧ         = Неопределено;
	
	Попытка
		ЭлементФормы.ПерейтиКПервойСтроке();
	Исключение
		//значит нет ни одной строки
		НадоПолучатьСтроки = Ложь;
	КонецПопытки;
	
	Если НадоПолучатьСтроки  Тогда
		Попытка
			ТекЭлемент = ЭлементФормы.ПолучитьТекстЯчейки();
			ЭлементФормы.ВыделитьВсеСтроки();
			ЗначениеТЧ = ЭлементФормы.ПолучитьВыделенныеСтроки();
		Исключение
			Отладка("Не смог получить строки для ТЧ " + ЭлементФормы.Имя);
		КонецПопытки;
	КонецЕсли;
	
	Возврат ЗначениеТЧ;
КонецФункции	

&НаКлиенте
Функция ПолучитьСостояниеЭлементаФормыTestClient(ЭлементФормы)
	СтруктураЗначения = Новый Структура;
	СтруктураЗначения.Вставить("Тип",ТипЗнч(ЭлементФормы));
	СтруктураЗначения.Вставить("Имя",ЭлементФормы.Имя);
	
	//Отладка("Получаю элемент. Имя=" + ЭлементФормы.Имя + ", Тип=" + ТипЗнч(ЭлементФормы));
	//Сообщить("ЭлементФормы.Тип=" + ТипЗнч(ЭлементФормы));
	
	
	Если ТипЗнч(ЭлементФормы) = Тип("ТестируемаяКнопкаФормы") Тогда
		СтруктураЗначения.Вставить("Имя",ЭлементФормы.Имя);
		СтруктураЗначения.Вставить("ТекстЗаголовка",ЭлементФормы.ТекстЗаголовка);
		СтруктураЗначения.Вставить("Вид",ЭлементФормы.Вид);
		Если ЭлементФормы.Вид = ВидКнопкиФормы.ОбычнаяКнопка Тогда
			СтруктураЗначения.Вставить("ТекущаяВидимость",ЭлементФормы.ТекущаяВидимость());
			СтруктураЗначения.Вставить("ТекущаяДоступность",ЭлементФормы.ТекущаяДоступность());
		КонецЕсли;	 
	ИначеЕсли ТипЗнч(ЭлементФормы) = Тип("ТестируемаяТаблицаФормы") Тогда
	
		//Сообщить("ЭлементФормы.Имя=" + ЭлементФормы.Имя + ", ЭлементФормы.Тип=" + ТипЗнч(ЭлементФормы));
		//Сообщить("ЭлементФормы.Тип=" + ТипЗнч(ЭлементФормы));
		
		СтруктураЗначения.Вставить("Имя",ЭлементФормы.Имя);
		СтруктураЗначения.Вставить("ТекстЗаголовка",ЭлементФормы.ТекстЗаголовка);
		
		ЗначениеТЧ = ПолучитьЗначениеТестируемаяТаблицаФормы(ЭлементФормы);
		СтруктураЗначения.Вставить("ЗначениеТЧ",ЗначениеТЧ);
		
	ИначеЕсли ТипЗнч(ЭлементФормы) = Тип("ТестируемаяГруппаФормы") Тогда
		СтруктураЗначения.Вставить("Имя",ЭлементФормы.Имя);
		СтруктураЗначения.Вставить("ТекстЗаголовка",ЭлементФормы.ТекстЗаголовка);
		СтруктураЗначения.Вставить("Вид",ЭлементФормы.Вид);
	ИначеЕсли ТипЗнч(ЭлементФормы) = Тип("ТестируемоеПолеФормы") Тогда
		СтруктураЗначения.Вставить("Имя",ЭлементФормы.Имя);
		СтруктураЗначения.Вставить("ТекстЗаголовка",ЭлементФормы.ТекстЗаголовка);
		СтруктураЗначения.Вставить("Вид",ЭлементФормы.Вид);
		
		
		
		
		
		Если ЭлементФормы.Вид = ВидПоляФормы.ПолеТабличногоДокумента Тогда
			Если ЭлементФормы.ТекущаяДоступность() Тогда
				ТабДок = ПолучитьТабДокИзTestClient(ЭлементФормы);
				СтруктураЗначения.Вставить("ТабДок",ТабДок);
			КонецЕсли;	 
		ИначеЕсли ЭлементФормы.Вид = ВидПоляФормы.ПолеКартинки Тогда
		ИначеЕсли ЭлементФормы.Вид = ВидПоляФормы.ПолеГеографическойСхемы Тогда
		ИначеЕсли ЭлементФормы.Вид = ВидПоляФормы.ПолеГрафическойСхемы Тогда
		ИначеЕсли ЭлементФормы.Вид = ВидПоляФормы.ПолеДендрограммы Тогда
		ИначеЕсли ЭлементФормы.Вид = ВидПоляФормы.ПолеДиаграммы Тогда
		ИначеЕсли ЭлементФормы.Вид = ВидПоляФормы.ПолеДиаграммыГанта Тогда
		ИначеЕсли ЭлементФормы.Вид = ВидПоляФормы.ПолеИндикатора Тогда
		ИначеЕсли ЭлементФормы.Вид = ВидПоляФормы.ПолеКалендаря Тогда
		ИначеЕсли ЭлементФормы.Вид = ВидПоляФормы.ПолеПолосыРегулирования Тогда
		Иначе	
			//для остальных надо сохранить представление данных
			Попытка
				Если ЭлементФормы.ТекущаяВидимость() Тогда
					СтруктураЗначения.Вставить("ПредставлениеДанных",ЭлементФормы.ПолучитьПредставлениеДанных());
				КонецЕсли;	 
			Исключение
				
			КонецПопытки;
		КонецЕсли;	 
		
		
		//СтруктураЗначения.Вставить("ТекущаяВидимость",ЭлементФормы.ТекущаяВидимость());
		//СтруктураЗначения.Вставить("ТекущаяДоступность",ЭлементФормы.ТекущаяДоступность());
		
		
		//Если ЭлементФормы.Вид = ВидПоляФормы.ПолеВвода Тогда
		//	Попытка
		//		СтруктураЗначения.Вставить("Текст",ЭлементФормы.ПолучитьТекстРедактирования());
		//	Исключение
		//		
		//	КонецПопытки;
		//КонецЕсли;
	ИначеЕсли ТипЗнч(ЭлементФормы) = Тип("ТестируемаяДекорацияФормы") Тогда
		СтруктураЗначения.Вставить("Имя",ЭлементФормы.Имя);
		СтруктураЗначения.Вставить("ТекстЗаголовка",ЭлементФормы.ТекстЗаголовка);
		СтруктураЗначения.Вставить("Вид",ЭлементФормы.Вид);
	КонецЕсли;	 
	
	Возврат СтруктураЗначения;
КонецФункции	

&НаКлиенте
Функция ПолучитьСостояниеФормыTestClient()
	Результат       = Новый Структура;
	МассивРезультат = Новый Массив;
	
	Если ТипЗнч(ОбъектКонтекстСохраняемый) <> Тип("Структура") Тогда
		Сообщить("Перемення КонтекстСохраняемый не содержит значений! Невозможно определить окно TestClient!");
		Возврат Неопределено;
	КонецЕсли;	 
	
	Если Не ОбъектКонтекстСохраняемый.Свойство("ТестовоеПриложение") Тогда
		Сообщить("Перемення КонтекстСохраняемый не содержит значения ""ТестовоеПриложение""! Невозможно определить окно TestClient!");
		Возврат Неопределено;
	КонецЕсли;	 
	
	
	Попытка
		АктивноеОкно = ОбъектКонтекстСохраняемый.ТестовоеПриложение.ПолучитьАктивноеОкно();
		ТекущаяФорма = АктивноеОкно.НайтиОбъект(Тип("ТестируемаяФорма"));
		Если ТекущаяФорма = Неопределено Тогда
			Сообщить("Активная форма не найдена!");
			Возврат Неопределено;
		КонецЕсли;	 
		
		Сообщить("Найдена форма: ТекстЗаголовка=" + ТекущаяФорма.ТекстЗаголовка + ", ИмяФормы=" + ТекущаяФорма.ИмяФормы);
	Исключение
		Сообщить("Ошибка при получении активной формы!");
		Сообщить("" + ОписаниеОшибки());
		Возврат Неопределено;
	КонецПопытки;
	
	
	ТекТЧ           = Неопределено;
	МассивЭлементов = ТекущаяФорма.НайтиОбъекты();
	Для каждого Элем Из МассивЭлементов Цикл
		//Если ТипЗнч(Элем) = Тип("ТестируемаяГруппаФормы") Тогда
		//	Продолжить;
		//КонецЕсли;	 
		
		
		//Если ТипЗнч(Элем) = Тип("ТестируемаяТаблицаФормы") Тогда
		//	ТекТЧ = Элем.Имя;
		//Иначе
			Если СокрЛП(ТекТЧ) <> "" Тогда
				Если Лев(Элем.Имя,СтрДлина(ТекТЧ)) = ТекТЧ Тогда
					//это подчиненный элемент ТЧ, а колонки ТЧ обрабатываются в другом месте
					Продолжить;
				КонецЕсли;	 
			КонецЕсли;	 
		//КонецЕсли;	 
		
		
		
		//Отладка("Получаю элемент. Имя=" + Элем.Имя + ", Тип=" + ТипЗнч(Элем));
		СостояниеЭлемента = ПолучитьСостояниеЭлементаФормыTestClient(Элем);
		МассивРезультат.Добавить(СостояниеЭлемента);
		
		//Сообщить("" + ТипЗнч(Элем) + ", " + Элем.Имя);
	КонецЦикла;
	
	Результат.Вставить("ИмяФормы",ТекущаяФорма.ИмяФормы);
	Результат.Вставить("МассивЭлементов",МассивРезультат);
	
	Возврат Результат;
КонецФункции	

&НаКлиенте
Процедура ЗапомнитьСостояниеФормыTestClient(Команда)
	СохраненноеСостояниеФормыTestClient = ПолучитьСостояниеФормыTestClient();
КонецПроцедуры

&НаКлиенте
Процедура ЗабытьСостояниеФормыTestClient() Экспорт
	СохраненноеСостояниеФормыTestClient = Неопределено;
КонецПроцедуры

&НаКлиенте
Процедура ЗабытьСостояниеФормыTestClientКнопка(Команда)
	ЗабытьСостояниеФормыTestClient();
КонецПроцедуры

&НаКлиенте
Функция ПолучитьЭлементИзСтруктурыПоИмени(Имя,Массив)
	Для каждого Элем Из Массив Цикл
		Если Элем.Имя = Имя Тогда
			Возврат Элем;
		КонецЕсли;	 
	КонецЦикла;
	
	Возврат Неопределено;
КонецФункции	

&НаКлиенте
Функция ВывестиИзмененияФормыGherkin(Было,Стало)
	Стр = "";
	
	Для каждого ЭлемСтало Из Стало.МассивЭлементов Цикл
		Имя = ЭлемСтало.Имя;
		
		Если Было <> Неопределено Тогда
			ЭлемБыло = ПолучитьЭлементИзСтруктурыПоИмени(Имя,Было.МассивЭлементов);
			Если ЭлемБыло = Неопределено Тогда
				Продолжить;
			КонецЕсли;	 
		КонецЕсли;	 
		
		
		Для каждого Свойство Из ЭлемСтало Цикл
			Ключ = Свойство.Ключ;
			
			Если Ключ = "ПредставлениеДанных" Тогда
				Если Было = Неопределено Тогда
					Изменение = "элемент формы с именем """ + ЭлемСтало.Имя + """ стал равен """ + ЭлемСтало.ПредставлениеДанных + """";
					
					Если Стр = "" Тогда
						Стр = Стр + "	Тогда " + Изменение + Символы.ПС;
					Иначе	
						Стр = Стр + "	И     " + Изменение + Символы.ПС;
					КонецЕсли;	 
				Иначе	
					Если НЕ ЭлемБыло.Свойство(Ключ) Тогда
						Продолжить;
					КонецЕсли;	 
					
					Если СокрЛП(ЭлемСтало[Ключ]) <> СокрЛП(ЭлемБыло[Ключ]) Тогда
						Изменение = "элемент формы с именем """ + ЭлемСтало.Имя + """ стал равен """ + ЭлемСтало.ПредставлениеДанных + """";
						
						Если Стр = "" Тогда
							Стр = Стр + "	Тогда " + Изменение + Символы.ПС;
						Иначе	
							Стр = Стр + "	И     " + Изменение + Символы.ПС;
						КонецЕсли;	 
						//Сообщить("Изменлось: " + ЭлемСтало.Имя);
						//Сообщить("Было:  " + ЭлемБыло[Ключ]);
						//Сообщить("Стало: " + ЭлемСтало[Ключ]);
					КонецЕсли;	 
				КонецЕсли;	 
			ИначеЕсли Ключ = "ТабДок" Тогда
				
				Если Было = Неопределено Тогда
					СтрТабДок = ПолучитьСтрокуТабличныйДокументФормаTestClient(ЭлемСтало[Ключ]);
					Если СтрТабДок = "" Тогда
						Изменение = "табличный документ формы с именем """ + ЭлемСтало.Имя + """ стал пустым";
						Если Стр = "" Тогда
							Стр = Стр + "	Тогда " + Изменение + Символы.ПС;
						Иначе	
							Стр = Стр + "	И     " + Изменение + Символы.ПС;
						КонецЕсли;	 
					Иначе	
						Изменение = "табличный документ формы с именем """ + ЭлемСтало.Имя + """ стал равен:";
						
						Если Стр = "" Тогда
							Стр = Стр + "	Тогда " + Изменение + Символы.ПС;
						Иначе	
							Стр = Стр + "	И     " + Изменение + Символы.ПС;
						КонецЕсли;	 
						
						Стр = Стр + СтрТабДок + Символы.ПС;
					КонецЕсли;	 
					
				КонецЕсли;	 
				
			ИначеЕсли Ключ = "ЗначениеТЧ" Тогда
				Если ЭлемСтало[Ключ] = Неопределено Тогда
					Продолжить;
				КонецЕсли;	 
				Если ЭлемСтало[Ключ].Количество() = 0 Тогда
					Продолжить;
				КонецЕсли;	 
				
				Если Было = Неопределено Тогда
					Изменение = "таблица формы с именем """ + ЭлемСтало.Имя + """ стала равной:";
					
					Если Стр = "" Тогда
						Стр = Стр + "	Тогда " + Изменение + Символы.ПС;
					Иначе	
						Стр = Стр + "	И     " + Изменение + Символы.ПС;
					КонецЕсли;	 
					
					СтрТЧ = ПолучитьСтрокуСТЧФормаTestClient(ЭлемСтало[Ключ]);
					
					Стр = Стр + СтрТЧ + Символы.ПС;
				Иначе
					//надо сравнить две ТЧ
					ТЧбыло  = ЭлемБыло[Ключ];
					ТЧстало = ЭлемСтало[Ключ];
					
					Если ТЧстало.Количество() = 0 Тогда
						Продолжить;
					КонецЕсли;	 
					
					Если ТЧбыло.Количество() <> ТЧстало.Количество() Тогда
						//значит изменилось количество строк, просто выводим новую таблицу
						Изменение = "таблица формы с именем """ + ЭлемСтало.Имя + """ стала равной:";
						
						Если Стр = "" Тогда
							Стр = Стр + "	Тогда " + Изменение + Символы.ПС;
						Иначе	
							Стр = Стр + "	И     " + Изменение + Символы.ПС;
						КонецЕсли;	 
						
						СтрТЧ = ПолучитьСтрокуСТЧФормаTestClient(ЭлемСтало[Ключ]);
						
						Стр = Стр + СтрТЧ + Символы.ПС;
						
						Продолжить;
					КонецЕсли;	 
					
					ФлагИзмененныеКолонки = Новый Массив;
					Для каждого СтрокаСтало Из ТЧстало Цикл
						Для каждого Колонка Из СтрокаСтало Цикл
							ФлагИзмененныеКолонки.Добавить(Ложь);
						КонецЦикла;	
						
						Прервать;
					КонецЦикла;	
					
					Ном = -1;
					Для каждого СтрокаСтало Из ТЧстало Цикл
						Ном        = Ном + 1;
						СтрокаБыло = ТЧбыло[Ном];
						
						идКолонки = -1;
						Для каждого Колонка Из СтрокаСтало Цикл
							идКолонки  = идКолонки + 1;
							
							ИмяКолонки = Колонка.Ключ;
							
							ЗначениеБыло  = СтрокаБыло[ИмяКолонки];
							ЗначениеСтало = СтрокаСтало[ИмяКолонки];
							
							Если ЗначениеБыло <> ЗначениеСтало Тогда
								ФлагИзмененныеКолонки[идКолонки] = Истина;
							КонецЕсли;	 
						КонецЦикла;
					
					КонецЦикла;
					
					
					ИзмененныеКолонки = Новый Массив;
					Для каждого СтрокаСтало Из ТЧстало Цикл
						Ном = -1;
						Для каждого Колонка Из СтрокаСтало Цикл
							Ном = Ном + 1;
							ИмяКолонки = Колонка.Ключ;
							Если ФлагИзмененныеКолонки[Ном] Тогда
								ИзмененныеКолонки.Добавить(ИмяКолонки);
							КонецЕсли;	 
						КонецЦикла;	
						
						Прервать;
					КонецЦикла;	
					
					
					Если ИзмененныеКолонки.Количество() = 0 Тогда
						Продолжить;
					КонецЕсли;	 
					
					
					Изменение = "таблица формы с именем """ + ЭлемСтало.Имя + """ содержит изменения:";
					Если Стр = "" Тогда
						Стр = Стр + "	Тогда " + Изменение + Символы.ПС;
					Иначе	
						Стр = Стр + "	И     " + Изменение + Символы.ПС;
					КонецЕсли;	 
					СтрТЧ = ПолучитьСтрокуСТЧФормаTestClient(ЭлемСтало[Ключ],ИзмененныеКолонки);
					
					Стр = Стр + СтрТЧ + Символы.ПС;
					
					
					
					
				КонецЕсли;	 
				
			КонецЕсли;	 
			
		КонецЦикла;
		
	КонецЦикла;
	
	
	Возврат Стр;
КонецФункции

&НаКлиенте
Процедура ФорматироватьМассивСтрокКакТаблицу(МассивСтрок)
	Если МассивСтрок.Количество() = 0 Тогда
		Возврат;
	КонецЕсли;	 
	
	Стр = СокрЛП(МассивСтрок[0]);
	Стр = Сред(Стр,2,СтрДлина(Стр)-2);
	МассивСтолбцов = РазложитьСтрокуВМассивПодстрок(Стр,"|");
	
	КолПараметров = МассивСтолбцов.Количество();
	МассивДлин = Новый Массив;
	Для каждого Элем Из МассивСтолбцов Цикл
		МассивДлин.Добавить(0);
	КонецЦикла;
	
	
	Для каждого Стр Из МассивСтрок Цикл
		Стр = Сред(Стр,2,СтрДлина(Стр)-2);
		МассивСтолбцов = РазложитьСтрокуВМассивПодстрок(Стр,"|");
		
		Для Ккк = 0 По МассивДлин.Количество()-1 Цикл
			Зн = СокрЛП(МассивСтолбцов[Ккк]);
			Зн = СтрЗаменить(Зн,ПредставлениеВертЧертыВТабДок,"|");
			
			ДлинаСтроки = СтрДлина(Зн);
			Если ДлинаСтроки > МассивДлин[Ккк] Тогда
				МассивДлин[Ккк] = ДлинаСтроки;
			КонецЕсли;	 
			
		КонецЦикла;
	КонецЦикла;
	
	Ном = -1;
	Для каждого Стр Из МассивСтрок Цикл
		Ном = Ном + 1;
		Стр = Сред(Стр,2,СтрДлина(Стр)-2);
		МассивСтолбцов = РазложитьСтрокуВМассивПодстрок(Стр,"|");
		
		СтрПараметров = "| ";
		Для Ккк = 0 По МассивДлин.Количество()-1 Цикл
			Зн = СокрЛП(МассивСтолбцов[Ккк]);
			Зн = СтрЗаменить(Зн,ПредставлениеВертЧертыВТабДок,"|");
			
			Пока СтрДлина(Зн) < МассивДлин[Ккк] Цикл
				Зн = Зн + " ";
			КонецЦикла;
			СтрПараметров = СтрПараметров + Зн + " | ";
		КонецЦикла;
		
		СтрПараметров = СокрЛП(СтрПараметров);
		
		//СтрПараметров = СтрЗаменить(СтрПараметров,ПредставлениеВертЧертыВТабДок,"|");
		МассивСтрок[Ном] = СтрПараметров;
	КонецЦикла;
	
КонецПроцедуры


&НаКлиенте
Функция ПолучитьСтрокуТабличныйДокументФормаTestClient(ТабДок)
	МассивСтрок = Новый Массив;
	
	Стр = "|";
	
	Для каждого СтрокаТабДок Из ТабДок Цикл
		СтрокаТЧ = "|";
		Для каждого КолонкаТабДок Из СтрокаТабДок Цикл
			СтрокаТЧ = СтрокаТЧ + " '" + СтрЗаменить(КолонкаТабДок,"|",ПредставлениеВертЧертыВТабДок) + "' |";
			
		КонецЦикла;
		МассивСтрок.Добавить(СтрокаТЧ);
	КонецЦикла;
	
	
	ФорматироватьМассивСтрокКакТаблицу(МассивСтрок);
	
	
	Стр = "";
	Для каждого Элем Из МассивСтрок Цикл
		Стр = Стр + Символы.Таб + Символы.Таб +  Элем + Символы.ПС;
	КонецЦикла;
	
	Возврат Стр;
КонецФункции	

&НаКлиенте
Функция ПолучитьСтрокуСТЧФормаTestClient(ТЧ,ИзмененныеКолонки = Неопределено)
	МассивСтрок = Новый Массив;
	
	Стр = "|";
	
	//шапка ТЧ
	Для каждого СтрТЧ Из ТЧ Цикл
		Для каждого Элем Из СтрТЧ Цикл
			Если ИзмененныеКолонки <> Неопределено Тогда
				//значит выводим только нужные колонки
				Если ИзмененныеКолонки.Найти(Элем.Ключ) = Неопределено Тогда
					Продолжить;
				КонецЕсли;	 
			КонецЕсли;	 
			
			Стр = Стр + " '" + Элем.Ключ + "' |";
		КонецЦикла;
		
		Прервать;
	КонецЦикла;
	
	МассивСтрок.Добавить(Стр);
	
	Для каждого СтрТЧ Из ТЧ Цикл
		СтрокаТЧ = "|";
		Для каждого Элем Из СтрТЧ Цикл
			Если ИзмененныеКолонки <> Неопределено Тогда
				//значит выводим только нужные колонки
				Если ИзмененныеКолонки.Найти(Элем.Ключ) = Неопределено Тогда
					Продолжить;
				КонецЕсли;	 
			КонецЕсли;	 
			
			СтрокаТЧ = СтрокаТЧ + " '" + Элем.Значение + "' |";
		КонецЦикла;
		
		МассивСтрок.Добавить(СтрокаТЧ);
	КонецЦикла;
	
	
	ФорматироватьМассивСтрокКакТаблицу(МассивСтрок);
	
	
	Стр = "";
	Для каждого Элем Из МассивСтрок Цикл
		Стр = Стр + Символы.Таб + Символы.Таб +  Элем + Символы.ПС;
	КонецЦикла;
	
	Возврат Стр;
КонецФункции	


&НаКлиенте
Процедура ПолучитьИзмененияФормы(Тип)
	ТекущееСостояниеФормы = ПолучитьСостояниеФормыTestClient();
	Если ТекущееСостояниеФормы = Неопределено Тогда
		Возврат;                                                                   
	КонецЕсли;	 
	
	Если СохраненноеСостояниеФормыTestClient <> Неопределено Тогда
		Если СохраненноеСостояниеФормыTestClient.ИмяФормы <> ТекущееСостояниеФормы.ИмяФормы Тогда
			Сообщить("Изменилось имя формы: было: " + СохраненноеСостояниеФормыTestClient.ИмяФормы + ", стало: " + ТекущееСостояниеФормы.ИмяФормы);
			Возврат;
		КонецЕсли;	 
	КонецЕсли;	 
	
	Если Тип = "Gherkin" Тогда
		Изменения = ВывестиИзмененияФормыGherkin(СохраненноеСостояниеФормыTestClient,ТекущееСостояниеФормы);
	Иначе
		ВызватьИсключение "Неизвестный тип вывода данных по изменению формы!";
	КонецЕсли;	 
	
	СгенерированныйСценарий = Изменения;
	
	ЭтаФорма.ТекущийЭлемент = Элементы.СгенерированныйСценарий;
	
	СделатьСообщение("Изменения формы обработаны!");
КонецПроцедуры

&НаКлиенте
Процедура ПолучитьИзмененияФормыGherkin() Экспорт
	ПолучитьИзмененияФормы("Gherkin");
КонецПроцедуры

&НаКлиенте
Процедура ПолучитьИзмененияФормыGherkinКнопка(Команда)
	ПолучитьИзмененияФормыGherkin();
КонецПроцедуры

&НаКлиенте
Процедура ПроверкаРаботыVanessaBehaviorВРежимеTestClientПриИзменении(Элемент)
	УстановитьВидимостьСлужебныхЭлементов();
КонецПроцедуры

&НаКлиенте
Процедура ПолучитьЗначенияДляВыполненияШага(ОбработкаТеста,ИмяПроцедуры,МассивПараметров)
	
КонецПроцедуры

&НаКлиенте
Функция ПолучитьВременнуюФичу(Стр)
	ИмяФайла = ПолучитьИмяВременногоФайла("feature");
	
	ЗТ = Новый ЗаписьТекста(ИмяФайла,"UTF-8",,Истина); 
	ЗТ.ЗаписатьСтроку("Функционал: Тест"); 
	ЗТ.ЗаписатьСтроку("Сценарий: Тестовый сценарий"); 
	ЗТ.ЗаписатьСтроку(Стр); 
	
	ЗТ.Закрыть();
	
	Возврат ИмяФайла; 
КонецФункции	

&НаКлиенте
Функция СоздатьСтруктураПараметровДляЗагрузкиШага(ПутьЗагрузки,ДвоичныеДанные)
	СтруктураПараметров = Новый Структура;
	СтруктураПараметров.Вставить("DebugLog",Объект.DebugLog);
	СтруктураПараметров.Вставить("ДополнительныеПараметры",Неопределено);
	СтруктураПараметров.Вставить("ИдетЗагрузкаИзКаталога",Ложь);
	СтруктураПараметров.Вставить("КаталогИнструментов",Объект.КаталогИнструментов);
	СтруктураПараметров.Вставить("КаталогФич",ПутьЗагрузки);
	СтруктураПараметров.Вставить("КаталогиБиблиотек",Объект.КаталогиБиблиотек);
	
	МассивРезультатОбходаКаталоговДляОднойФичи = Новый Массив;
	ф = Новый Файл(ПутьЗагрузки);
	СтруткураФайла = ПолучитьСтруткураФайлаФичи(1,ф.ИмяБезРасширения,ф.ПолноеИмя,ДвоичныеДанные);
	МассивРезультатОбходаКаталоговДляОднойФичи.Добавить(СтруткураФайла);
	
	СтруктураПараметров.Вставить("МассивРезультатОбходаКаталогов",МассивРезультатОбходаКаталоговДляОднойФичи);
	СтруктураПараметров.Вставить("МассивСообщений",Новый Массив);
	//СтруктураПараметров.Вставить("ПутьКОбработке",Объект.DebugLog);
	СтруктураПараметров.Вставить("СписокТеговИсключение",Объект.СписокТеговИсключение);
	СтруктураПараметров.Вставить("СписокТеговОтбор",Объект.СписокТеговОтбор);
	СтруктураПараметров.Вставить("УдалитьСтрокуФичиИзДерева",Ложь);
	
	СтруктураПараметров.Вставить("ТаблицаУжеСуществующихСценариевУФ",ТаблицаУжеСуществующихСценариев);
	
	
	ДвДанныеvbFeatureReader = Новый ДвоичныеДанные(ПолучитьПутьКFeatureReader());
	СтруктураПараметров.Вставить("ДвДанныеvbFeatureReader",ДвДанныеvbFeatureReader);
	
	Возврат СтруктураПараметров;
КонецФункции	

&НаСервере
Процедура ЗагрузитьВременнуюФичуСервер(СтруктураПараметров)
	ВременноеИмяФайла = ПолучитьИмяВременногоФайла("epf");
	СтруктураПараметров.ДвДанныеvbFeatureReader.Записать(ВременноеИмяФайла);
	FeatureReader = ВнешниеОбработки.Создать(ВременноеИмяФайла,Ложь);
	
	ТзнТаблицаИзвестныхStepDefinition = РеквизитФормыВЗначение("ТаблицаИзвестныхStepDefinition");
	
	
	
	
	
	Дерево = Новый ДеревоЗначений;
	ОбъектСервер = РеквизитФормыВЗначение("Объект");
	ОбъектСервер.СоздатьКолонкиДерева(Дерево);
	
	Если Не СтруктураПараметров.Свойство("ТаблицаУжеСуществующихСценариев") Тогда
		ТаблицаУжеСуществующихСценариевСервер = ПреобразоватьМассивТаблицаУжеСуществующихСценариевВТаблицуЗначений(СтруктураПараметров.ТаблицаУжеСуществующихСценариевУФ);
		СтруктураПараметров.Вставить("ТаблицаУжеСуществующихСценариев",ТаблицаУжеСуществующихСценариевСервер);
	КонецЕсли;	 
	
	
	//СтруктураПараметров = Неопределено;
	//ТзнТаблицаИзвестныхStepDefinition = Неопределено;
	
	ПерваяСтрокаДерева = Дерево.Строки.Добавить();
	ПерваяСтрокаДерева.Имя = "Фичи";
	ПерваяСтрокаДерева.ПолныйПуть = "";
	
	FeatureReader.ЗагрузитьФичу(СтруктураПараметров.КаталогФич,ПерваяСтрокаДерева.Строки,ТзнТаблицаИзвестныхStepDefinition,СтруктураПараметров);
	
	
	
	Если СтруктураПараметров.Свойство("КешФич") Тогда
		СтруктураПараметров.КешФич = Неопределено;
	КонецЕсли;	 
	
	Если СтруктураПараметров.Свойство("ТаблицаУжеСуществующихСценариев") Тогда
		СтруктураПараметров.ТаблицаУжеСуществующихСценариев = Неопределено;
	КонецЕсли;	 
	
	Шаги = Новый Массив;
	ПолучитьШагиИзДерева(Дерево.Строки,Шаги);
	
	СтруктураПараметров.Вставить("Шаги",Шаги);	
КонецПроцедуры

&НаСервере
Процедура ПолучитьШагиИзДерева(ДеревоСтроки,Шаги)
	Для каждого СтрокаДерева Из ДеревоСтроки Цикл
		Если СтрокаДерева.Шаг = Истина Тогда
			Шаг = Новый Структура;
			Шаг.Вставить("Имя",СтрокаДерева.Имя);
			Шаг.Вставить("СтрокаРеальнойПроцедуры",СтрокаДерева.СтрокаРеальнойПроцедуры);
			Шаг.Вставить("ЗначенияПараметров",СтрокаДерева.ЗначенияПараметров);
			Шаг.Вставить("АдресСнипета",СтрокаДерева.АдресСнипета);
			Шаг.Вставить("ШагСПараметрамиВТаблице",СтрокаДерева.ШагСПараметрамиВТаблице);
			
			Если СтрокаДерева.ШагСПараметрамиВТаблице = Истина Тогда
				ПарамТаблица = Новый Массив;
				
				ПодчиненныеСтроки = СтрокаДерева.Строки;
				Для каждого СтрокиТаблицы Из ПодчиненныеСтроки Цикл
					СтрокаПарамТаблица = Новый Структура;
					
					НомерКолонки = 0;
					Для каждого Колонка Из СтрокиТаблицы.ПараметрыТаблицы Цикл
						НомерКолонки       = НомерКолонки + 1;
						СтруктураПараметра = Колонка.Значение;
						Значение           = ПолучитьЗначениеДляПередачиВМетодСервер(СтруктураПараметра.Значение,СтруктураПараметра.Тип);
						Значение           = Вычислить(Значение);
						
						СтрокаПарамТаблица.Вставить("Кол" + НомерКолонки,Значение);
					КонецЦикла;
					
					ПарамТаблица.Добавить(СтрокаПарамТаблица);
				КонецЦикла;
				Шаг.Вставить("ПарамТаблица",ПарамТаблица);
			КонецЕсли;	 
			
			
			Шаги.Добавить(Шаг);
		Иначе	
			ПолучитьШагиИзДерева(СтрокаДерева.Строки,Шаги);
		КонецЕсли;	 
	КонецЦикла;
КонецПроцедуры	

&НаКлиенте
Функция ПолучитьМассивПараметровИзСписокАргументов(СписокАргументов)
	МассивПараметров = Новый Массив;
	Для Каждого ЭлементМассива Из СписокАргументов Цикл
		Элем = ЭлементМассива.Значение;
		МассивПараметров.Добавить(ПолучитьЗначениеДляПередачиВМетод(Элем.Значение,Элем.Тип));
	КонецЦикла;
	
	Возврат МассивПараметров;
КонецФункции	

&НаКлиенте
Процедура ПодготовитьИВызватьМетод(ТекШаг,ОбработкаТеста,ИмяПроцедуры,МассивПараметров)
	ОбработкаТеста.Контекст            = ОбъектКонтекст;
	ОбработкаТеста.КонтекстСохраняемый = ОбъектКонтекстСохраняемый;
	
	Если Объект.ДелатьЛогВыполненияСценариевВЖР Тогда
		ЗаписатьЛогВЖРПередВыполнениемШага(ТекШаг.Имя);
	КонецЕсли;	 
	
	ВсёЕщёИдётВыполнениеШагов = Истина;
	ВызватьМетод(ОбработкаТеста, ИмяПроцедуры, МассивПараметров);
	ВсёЕщёИдётВыполнениеШагов = Ложь;
	
	ОбъектКонтекст            = ОбработкаТеста.Контекст;
	ОбъектКонтекстСохраняемый = ОбработкаТеста.КонтекстСохраняемый;
КонецПроцедуры

&НаКлиенте
Процедура Шаг(Стр) Экспорт
	ВременнаяФича = ПолучитьВременнуюФичу(Стр);
	ДвоичныеДанные = Новый ДвоичныеДанные(ВременнаяФича);
	
	СтруктураПараметров = СоздатьСтруктураПараметровДляЗагрузкиШага(ВременнаяФича,ДвоичныеДанные);
	ЗагрузитьВременнуюФичуСервер(СтруктураПараметров);
	
	Шаги = СтруктураПараметров.Шаги;
	Для каждого ТекШаг Из Шаги Цикл
		Если Не ЗначениеЗаполнено(ТекШаг.АдресСнипета) Тогда
			ВызватьИсключение "Для шага <" + ТекШаг.Имя + "> не найден EPF файл!";
		КонецЕсли;	 
		
		ИмяПроцедуры     = ТекШаг.СтрокаРеальнойПроцедуры;
		СписокАргументов = ТекШаг.ЗначенияПараметров;
		
		МассивПараметров = ПолучитьМассивПараметровИзСписокАргументов(СписокАргументов);
		Если ТекШаг.ШагСПараметрамиВТаблице = Истина Тогда
			МассивПараметров.Добавить(ТекШаг.ПарамТаблица);
		КонецЕсли;	 
		
		АдресСнипета   = ТекШаг.АдресСнипета;
		ОбработкаТеста = ПолучитьКонтекстТестаПоАдресСнипета(АдресСнипета);
		
		ПодготовитьИВызватьМетод(ТекШаг,ОбработкаТеста,ИмяПроцедуры,МассивПараметров);
		
	КонецЦикла;
КонецПроцедуры

&НаКлиенте
Процедура ДляВызоваКонфигуратора(Команда)
	Зн = 1/0;
КонецПроцедуры


&НаКлиенте
Процедура ДляСлужебногоОповещения()
	Оповестить("СлужебноеОповещение", "СлужебноеОповещение");
КонецПроцедуры

&НаКлиенте
Процедура СделатьСлужебноеОповещение()Экспорт
	ПодключитьОбработчикОжидания("ДляСлужебногоОповещения",1,Истина);
КонецПроцедуры


&НаКлиенте
Функция НайтиФормыТекущегоОкна()
	ОкноПриложения         = ПолучитьАктивноеОкноИзТестовоеПриложение();
	МассивФорм             = ОкноПриложения.НайтиОбъекты(Тип("ТестируемаяФорма"));
	Возврат МассивФорм;
КонецФункции

&НаКлиенте
Функция ПолучитьЗначениеРеквизитаОткрытойФормыПоЗаголовку(ИмяРеквизита,ИскатьПоИмени = Ложь)Экспорт
	Нашли = Ложь;
	МассивФорм = НайтиФормыТекущегоОкна();
	Для каждого ТекущаяФорма Из МассивФорм Цикл
		
		Если ИскатьПоИмени Тогда
			МассивЭлементов        = ТекущаяФорма.НайтиОбъекты(,, ИмяРеквизита);
		Иначе
			МассивЭлементов        = ТекущаяФорма.НайтиОбъекты(, ИмяРеквизита);
		КонецЕсли;	 
		
		Если МассивЭлементов = Неопределено Тогда
			Продолжить;
			//Стр = "Элемента формы с заголовком <" + ИмяРеквизита + "> не найдено.";
			//Сообщить(Стр);
			//ВызватьИсключение Стр;
		КонецЕсли;	 
		
		Если МассивЭлементов.Количество() = 0 Тогда
			Продолжить;
			//Стр = "Элемента формы с заголовком <" + ИмяРеквизита + "> не найдено.";
			//Сообщить(Стр);
			//ВызватьИсключение Стр;
		КонецЕсли;	 
		
		Если МассивЭлементов.Количество() > 1  Тогда
			Сообщить("Обнаружено несколько полей с заголовком <" + ИмяРеквизита + ">");
			Ном = 0;
			Для каждого Элем Из МассивЭлементов Цикл
				Ном = Ном + 1;
				Сообщить("№" + Ном + ". Заголовок=<" + Элем.ТекстЗаголовка  + ">. Имя=<" + Элем.Имя + ">. ТекстПоля = <" + Элем.ПолучитьПредставлениеДанных() + ">");
			КонецЦикла;
			
			Стр = "Найдено более одного поля формы с заголовком <" + ИмяРеквизита + ">. Рекомендуется искать элемент по имени.";
			Сообщить(Стр);
			ВызватьИсключение Стр;
		КонецЕсли;	 
		
		ПолеРеквизит = МассивЭлементов[0];
		
		
		//ПолеРеквизит.Активизировать();
		//ПолеРеквизит.ВвестиТекст(Текст);
		Тип = ТипЗнч(ПолеРеквизит);
		
		Если Тип = Тип("ТестируемоеПолеФормы") Тогда
			Возврат ПолеРеквизит.ПолучитьПредставлениеДанных();
		ИначеЕсли Тип = Тип("ТестируемаяТаблицаФормы") Тогда
			ТабДок = ПолучитьЗначениеТестируемаяТаблицаФормы(ПолеРеквизит);
			Возврат ТабДок;
		КонецЕсли;	 
		
		Нашли = Истина;
		Прервать;
	КонецЦикла;
	
	Если НЕ Нашли Тогда
		Если ИскатьПоИмени Тогда
			Стр = "Элемента формы с именем <" + ИмяРеквизита + "> не найдено.";
		Иначе	
			Стр = "Элемента формы с заголовком <" + ИмяРеквизита + "> не найдено.";
		КонецЕсли;	 
		
		Сообщить(Стр);
		ВызватьИсключение Стр;
	КонецЕсли;	 
	
КонецФункции

&НаКлиенте
Функция ПолучитьЗначениеРеквизитаОткрытойФормыПоИмени(ИмяРеквизита)Экспорт
	Возврат ПолучитьЗначениеРеквизитаОткрытойФормыПоЗаголовку(ИмяРеквизита,Истина);
КонецФункции


//{снятие скриншота
&НаКлиенте
Функция СформироватьИмяФайлаСкриншота(ОписаниеШага,СтрокаСценария)
	УИД = Новый УникальныйИдентификатор;
	
	Стр = "" + УИД + "-attachment.png";
	
	Каталог = Объект.КаталогOutputСкриншоты;
	Если НЕ ФайлСуществуетКомандаСистемы(Каталог) Тогда
		СоздатьКаталогКомандаСистемы(Каталог);
	КонецЕсли;	 
	
	Стр = Каталог + "\" + Стр;
	
	Возврат Стр;
КонецФункции	

&НаКлиенте
Процедура ЗаполнитьМассивPIDПоИмениПроцесса(ИмяПроцесса,Массив)
	ЛогФайл = ПолучитьИмяВременногоФайла("txt");
	Команда = "tasklist /FI ""IMAGENAME eq " + ИмяПроцесса +  """ /nh > " + ЛогФайл;
	ВыполнитьКомандуОСБезПоказаЧерногоОкна(Команда);
	
	Если НЕ ФайлСуществуетКомандаСистемы(ЛогФайл) Тогда
		СделатьСообщение("Ошибка при получении списка процессов 1С!");
		Возврат;
	КонецЕсли;	 
	
	Текст = Новый ЧтениеТекста;
	Текст.Открыть(ЛогФайл,"UTF-8");
	
	Пока Истина Цикл
		Стр = Текст.ПрочитатьСтроку();
		Если Стр = Неопределено Тогда
			Прервать;
		КонецЕсли;	 
		
		
		Если СокрЛП(Стр) = "" Тогда
			Продолжить;
		КонецЕсли;	 
		
		Стр = НРег(Стр);
		Стр = СокрЛП(СтрЗаменить(Стр,НРег(ИмяПроцесса),""));
		Поз = Найти(Стр," ");
		PID = Лев(Стр,Поз-1);
		Попытка
			PID = Число(PID);
			Массив.Добавить(PID);
		Исключение
			СделатьСообщение("Не смог преобразовать к числу PID=" + PID);
		КонецПопытки;
		
	КонецЦикла;	
	
	Текст.Закрыть();
	
КонецПроцедуры

&НаКлиенте
Функция ПолучитьМассивPIDОкон1С()
	Рез = Новый Массив;
	
	ЗаполнитьМассивPIDПоИмениПроцесса("1cv8.exe",Рез);
	ЗаполнитьМассивPIDПоИмениПроцесса("1cv8c.exe",Рез);
	
	//Для каждого Элем Из Рез Цикл
	//	Сообщить("" + Элем);
	//КонецЦикла;
	
	Возврат Рез;
	
КонецФункции	


&НаКлиенте
Процедура ПолучитьМассивСкриншотовКаждогоОкна1С()
	
	
	
	
	
	//ProcessID = МассивPIDОкон1С[ТекProcessID];
	//WshShell = Новый COMОбъект("WScript.Shell");
	//Рез      = WshShell.AppActivate(ProcessID);
	//
	//WshShell = Неопределено;
	
	//Сообщить("AppActivate=" + Рез);
	
	ИмяФайлаСкриншота = СформироватьИмяФайлаСкриншота(ЗначениеПараметровДляСнятияСкриншотов.ОписаниеШага,ЗначениеПараметровДляСнятияСкриншотов.СтрокаСценария);
	СделатьСкриншот(ИмяФайлаСкриншота);
	
	
	РезультатПрохожденияТестовСценария = ЗначениеПараметровДляСнятияСкриншотов.РезультатПрохожденияТестовСценария;
	Если НЕ РезультатПрохожденияТестовСценария.Свойство("МассивСкриншотов") Тогда
		МассивСкриншотов = Новый Массив();
		РезультатПрохожденияТестовСценария.Вставить("МассивСкриншотов",МассивСкриншотов);
	Иначе
		МассивСкриншотов = РезультатПрохожденияТестовСценария.МассивСкриншотов;
	КонецЕсли;	 
	
	ФайлИмяФайлаСкриншота = Новый Файл(ИмяФайлаСкриншота);
	
	СтруктураСкриншот = Новый Структура;
	СтруктураСкриншот.Вставить("ИмяФайла",ФайлИмяФайлаСкриншота.Имя);
	СтруктураСкриншот.Вставить("ДвоичныеДанные",Новый ДвоичныеДанные(ИмяФайлаСкриншота));
	МассивСкриншотов.Добавить(СтруктураСкриншот);
	
	//ПодключитьОбработчикОжидания("ПолучитьМассивСкриншотовКаждогоОкна1С",1,Истина);
	
	
	ПерейтиКВыполнениюСледующегоСценария();
КонецПроцедуры

&НаКлиенте
Процедура СделатьСкриншотВозникновенияОшибки(ОписаниеШага,СтрокаСценария,РезультатПрохожденияТестовСценария)
	Если Не Объект.ДелатьСкриншотПриВозникновенииОшибки Тогда
		Возврат;
	КонецЕсли;	 
	//МассивPIDОкон1С = ПолучитьМассивPIDОкон1С();
	ЗначениеПараметровДляСнятияСкриншотов = Новый Структура;
	ЗначениеПараметровДляСнятияСкриншотов.Вставить("ОписаниеШага",ОписаниеШага);
	ЗначениеПараметровДляСнятияСкриншотов.Вставить("СтрокаСценария",СтрокаСценария);
	ЗначениеПараметровДляСнятияСкриншотов.Вставить("РезультатПрохожденияТестовСценария",РезультатПрохожденияТестовСценария);
	
	ТекProcessID = -1;
	ПодключитьОбработчикОжидания("ПолучитьМассивСкриншотовКаждогоОкна1С",1,Истина);
	
КонецПроцедуры
//}снятие скриншота



//{получить состояние выполнения сценариев
&НаКлиенте
Функция ПолучитьСостояниеVanessaBehavior() Экспорт 
	Рез        = Новый Структура;
	
	ТекущаяФича = Новый Структура;
	ТекущаяФича.Вставить("Имя",Неопределено);
	ТекущаяФича.Вставить("ПолныйПуть",Неопределено);
	
	
	ТекущийСценарий = Новый Структура;
	ТекущийСценарий.Вставить("Имя",Неопределено);
	
	ТекущийШаг = Новый Структура;
	ТекущийШаг.Вставить("Имя",Неопределено);
	
	Рез.Вставить("ТекущаяФича",ТекущаяФича);
	Рез.Вставить("ТекущийСценарий",ТекущийСценарий);
	Рез.Вставить("ТекущийШаг",ТекущийШаг);
	
	Если (МассивСценариевДляВыполнения.Количество()-1) < ТекИД_СценарияВМассиве Тогда
		Возврат Рез;
	КонецЕсли;	 
	
	
	
	ТекущийСценарий.Вставить("Имя",МассивСценариевДляВыполнения[ТекИД_СценарияВМассиве].Имя);
	
	ТекущаяФича.Вставить("Имя",МассивСценариевДляВыполнения[ТекИД_СценарияВМассиве].ИмяФичи);
	ТекущаяФича.Вставить("ПолныйПуть",МассивСценариевДляВыполнения[ТекИД_СценарияВМассиве].ПолныйПутьКФиче);
	
	
	Шаги   = МассивСценариевДляВыполнения[ТекИД_СценарияВМассиве].Шаги;
	
	
	Если (Шаги.Количество()-1) < ТекИД_ШагаВМассиве Тогда
		Возврат Рез;
	КонецЕсли;	 
	
	Если ТекИД_ШагаВМассиве < 0 Тогда
		Возврат Рез;
	КонецЕсли;	 
	
	
	ТекШаг = Шаги[ТекИД_ШагаВМассиве];
	ТекущийШаг.Вставить("Имя",ТекШаг.Имя);
	ТекущийШаг.Вставить("ЗначенияПараметров",ТекШаг.ЗначенияПараметров.Скопировать());
	
	
	Возврат Рез;
	
КонецФункции	 
//}получить состояние выполнения сценариев





//рисует рамку вокруг активного элемента формы
&НаКлиенте
Процедура ПодсветитьАктивноеОкно(Длительность,ЖдатьЗавершения = Истина) Экспорт
	ПутьКПриложению = Объект.КаталогСкриптовСборкиВидео + "\uihelper\FrameShow\FrameShow.exe";
	Если Не ФайлСуществуетКомандаСистемы(ПутьКПриложению) Тогда
		Возврат;
	КонецЕсли;	 
	
	Путь = ПутьКПриложению + " -showframeofactivecontrol timeshowframe=" + СтрЗаменить(Длительность,Символы.НПП,"");
	Если ЕстьПоддержкаАсинхронныхВызовов Тогда
		Если ЖдатьЗавершения Тогда
			ВыполнитьКомандуОСБезПоказаЧерногоОкна(Путь);	
		Иначе	
			ВыполнитьКомандуОСБезПоказаЧерногоОкна(Путь,0);	
		КонецЕсли;	 
	Иначе
		ЗапуститьПриложение(Путь,,ЖдатьЗавершения);
	КонецЕсли;	 
КонецПроцедуры

&НаКлиенте
Процедура ПодсветитьАктивныйЭлементФормы() Экспорт
	Если НЕ ЗначениеЗаполнено(Объект.КаталогСкриптовСборкиВидео) Тогда
		Возврат;
	КонецЕсли;	
	
	Если Не Объект.ИдетЗаписьВидео Тогда
		Возврат;
	КонецЕсли;	 
	
	
	ПодсветитьАктивноеОкно(2000,Истина);
	
КонецПроцедуры

&НаКлиенте
Процедура ПодсветитьАктивныйЭлементФормыHTML() Экспорт
	Если НЕ ЗначениеЗаполнено(Объект.КаталогСкриптовСборкиВидео) Тогда
		Возврат;
	КонецЕсли;	
	
	Если Не Объект.СоздаватьИнструкциюHTML и Не Объект.СоздаватьИнструкциюMarkdown Тогда
		Возврат;
	КонецЕсли;	 
	
	
	ПодсветитьАктивноеОкно(20000,Ложь);
	
	Sleep(3);
КонецПроцедуры

&НаКлиенте
Процедура УбратьПодсветкуАктвиногоЭлемента() Экспорт
	TASKKILL("FrameShow.exe");
КонецПроцедуры


//перемещает курсор у активному объекту
&НаКлиенте
Процедура СделатьДействияПриЗаписиИнструкции(ПарамСтр = "")Экспорт
	СделатьДействияПриЗаписиHTML(ПарамСтр);
	СделатьДействияПриЗаписиВидео(ПарамСтр);
КонецПроцедуры

&НаКлиенте
Процедура СделатьДействияПриЗаписиВидео(ПарамСтр = "") Экспорт
	Если Объект.ИдетЗаписьВидео Тогда
		Если ПарамСтр = "толькофрейм" Тогда
			ПодсветитьАктивныйЭлементФормы();
		ИначеЕсли ПарамСтр = "толькомышь" Тогда
			ПереместитьКурсорМышиКАктивномуОбъекту();
		ИначеЕсли ПарамСтр = "толькоскриншот" Тогда
		Иначе	
			ПереместитьКурсорМышиКАктивномуОбъекту();
			ПодсветитьАктивныйЭлементФормы();
		КонецЕсли;	 
	КонецЕсли;	 
КонецПроцедуры

&НаКлиенте
Процедура СделатьДействияПриЗаписиHTML(ПарамСтр = "") Экспорт
	
	Попытка
		Шаги   = МассивСценариевДляВыполнения[ТекИД_СценарияВМассиве].Шаги;
		ТекШаг = Шаги[ТекИД_ШагаВМассиве];
		Если ТекШаг.ЭтоШагКонтекста Тогда
			Возврат;
		КонецЕсли;	 
	Исключение
	
	КонецПопытки;
	
	
	Если Объект.СоздаватьИнструкциюHTML Тогда
		Если ПарамСтр = "толькофрейм" Тогда
			ПодсветитьАктивныйЭлементФормыHTML();
		ИначеЕсли ПарамСтр = "толькомышь" Тогда
			ПереместитьКурсорМышиКАктивномуОбъектуHTML();
		ИначеЕсли ПарамСтр = "толькоскриншот" Тогда
		Иначе	
			ПереместитьКурсорМышиКАктивномуОбъектуHTML();
			ПодсветитьАктивныйЭлементФормыHTML();
		КонецЕсли;	 
		
		ДобавитьВЛогИнструкцииHTMLВыполненияШага();
		СкриншотСделанВСценарии = Истина;
		УбратьПодсветкуАктвиногоЭлемента();
	КонецЕсли;	 
	
	Если Объект.СоздаватьИнструкциюMarkdown Тогда
		Если ПарамСтр = "толькофрейм" Тогда
			ПодсветитьАктивныйЭлементФормыHTML();
		ИначеЕсли ПарамСтр = "толькомышь" Тогда
			ПереместитьКурсорМышиКАктивномуОбъектуHTML();
		ИначеЕсли ПарамСтр = "толькоскриншот" Тогда
		Иначе	
			ПереместитьКурсорМышиКАктивномуОбъектуHTML();
			ПодсветитьАктивныйЭлементФормыHTML();
		КонецЕсли;	 
		
		ДобавитьВЛогИнструкцииMarkdownВыполненияШага();
		СкриншотСделанВСценарии = Истина;
		УбратьПодсветкуАктвиногоЭлемента();
	КонецЕсли;	 
КонецПроцедуры


&НаКлиенте
Процедура ПереместитьКурсорМышиКАктивномуОкну(Скорость,ЖдатьЗавершения = Истина) Экспорт
	ПутьКПриложению = Объект.КаталогСкриптовСборкиВидео + "\uihelper\MouseMove\MouseMove.exe";
	Если Не ФайлСуществуетКомандаСистемы(ПутьКПриложению) Тогда
		Возврат;
	КонецЕсли;	 
	
	Путь = ПутьКПриложению + " -movemousetoactivecontrol mousespeed=" + СтрЗаменить(Скорость,Символы.НПП,"");
	//Путь = ПутьКПриложению + " -movemousetoactivecontrol mousespeed=" + СтрЗаменить(Скорость,Символы.НПП,"") + " -dolog logpath=c:\temp\111.txt";
	Если ЕстьПоддержкаАсинхронныхВызовов Тогда
		Если ЖдатьЗавершения Тогда
			ВыполнитьКомандуОСБезПоказаЧерногоОкна(Путь);	
		Иначе	
			ВыполнитьКомандуОСБезПоказаЧерногоОкна(Путь,0);	
		КонецЕсли;	 
	Иначе
		ЗапуститьПриложение(Путь,,ЖдатьЗавершения);
	КонецЕсли;	 
КонецПроцедуры

&НаКлиенте
Процедура ПереместитьКурсорМышиКАктивномуОбъекту() Экспорт
	Если НЕ ЗначениеЗаполнено(Объект.КаталогСкриптовСборкиВидео) Тогда
		Возврат;
	КонецЕсли;	
	
	Если Не Объект.ИдетЗаписьВидео Тогда
		Возврат;
	КонецЕсли;	 
	
	ПереместитьКурсорМышиКАктивномуОкну(500);
КонецПроцедуры

&НаКлиенте
Процедура ПереместитьКурсорМышиКАктивномуОбъектуHTML() Экспорт
	Если НЕ ЗначениеЗаполнено(Объект.КаталогСкриптовСборкиВидео) Тогда
		Возврат;
	КонецЕсли;	
	
	Если Не Объект.СоздаватьИнструкциюHTML И НЕ Объект.СоздаватьИнструкциюMarkdown Тогда
		Возврат;
	КонецЕсли;	 
	
	ПереместитьКурсорМышиКАктивномуОкну(50);
КонецПроцедуры










//{выбор каталогов
&НаКлиенте
Процедура КаталогиБиблиотекЗначениеНачалоВыбора(Элемент, ДанныеВыбора, СтандартнаяОбработка)
	СтандартнаяОбработка = Ложь;
	
	ТекущиеДанные = Элементы.КаталогиБиблиотек.ТекущиеДанные;
	
	ДиалогВыбораКаталога = Новый ДиалогВыбораФайла(РежимДиалогаВыбораФайла.ВыборКаталога);
	
	ДиалогВыбораКаталога.МножественныйВыбор = Ложь;
	
	ДиалогВыбораКаталога.Показать(Вычислить("Новый ОписаниеОповещения(""КаталогиБиблиотекЗначениеНачалоВыбораЗавершение"", ЭтотОбъект, ТекущиеДанные)"));
КонецПроцедуры

&НаКлиенте
Процедура КаталогиБиблиотекЗначениеНачалоВыбораЗавершение(ВыбранныеФайлы, ТекущиеДанные) Экспорт
	Если Ложь
		Или ВыбранныеФайлы = Неопределено
		Или ВыбранныеФайлы.Количество() = 0
		Тогда
		
		Возврат;
	КонецЕсли;
	
	Для Каждого Строка Из Объект.КаталогиБиблиотек Цикл
	Если ПустаяСтрока(Строка.Значение) Тогда
		Строка.Значение = ВыбранныеФайлы[0];
		
		Прервать;	
	КонецЕсли;
КонецЦикла;
КонецПроцедуры


&НаКлиенте
Процедура КаталогOutputAllureНачалоВыбора(Элемент, ДанныеВыбора, СтандартнаяОбработка)
	СтандартнаяОбработка = Ложь;

	ДиалогВыбораКаталога = Новый ДиалогВыбораФайла(РежимДиалогаВыбораФайла.ВыборКаталога);
	
	ДиалогВыбораКаталога.МножественныйВыбор = Ложь;
	
	ДиалогВыбораКаталога.Показать(Вычислить("Новый ОписаниеОповещения(""КаталогOutputAllureНачалоВыбораЗавершение"", ЭтотОбъект)"));
КонецПроцедуры

&НаКлиенте
Процедура КаталогOutputAllureНачалоВыбораЗавершение(ВыбранныеФайлы, ТекущиеДанные) Экспорт
	Если Ложь
		Или ВыбранныеФайлы = Неопределено
		Или ВыбранныеФайлы.Количество() = 0
		Тогда
		
		Возврат;
	КонецЕсли;
	
	Объект.КаталогOutputAllure = ВыбранныеФайлы[0];
КонецПроцедуры


&НаКлиенте
Процедура КаталогOutputСкриншотыНачалоВыбора(Элемент, ДанныеВыбора, СтандартнаяОбработка)
	СтандартнаяОбработка = Ложь;

	ДиалогВыбораКаталога = Новый ДиалогВыбораФайла(РежимДиалогаВыбораФайла.ВыборКаталога);
	
	ДиалогВыбораКаталога.МножественныйВыбор = Ложь;
	
	ДиалогВыбораКаталога.Показать(Вычислить("Новый ОписаниеОповещения(""КаталогOutputСкриншотыЗавершение"", ЭтотОбъект)"));
КонецПроцедуры

&НаКлиенте
Процедура КаталогOutputСкриншотыЗавершение(ВыбранныеФайлы, ТекущиеДанные) Экспорт
	Если Ложь
		Или ВыбранныеФайлы = Неопределено
		Или ВыбранныеФайлы.Количество() = 0
		Тогда
		
		Возврат;
	КонецЕсли;
	
	Объект.КаталогOutputСкриншоты = ВыбранныеФайлы[0];
КонецПроцедуры


&НаКлиенте
Процедура КаталогOutputxUnitНачалоВыбора(Элемент, ДанныеВыбора, СтандартнаяОбработка)
	СтандартнаяОбработка = Ложь;

	ДиалогВыбораКаталога = Новый ДиалогВыбораФайла(РежимДиалогаВыбораФайла.ВыборКаталога);
	
	ДиалогВыбораКаталога.МножественныйВыбор = Ложь;
	
	ДиалогВыбораКаталога.Показать(Вычислить("Новый ОписаниеОповещения(""КаталогOutputxUnitНачалоВыбораЗавершение"", ЭтотОбъект)"));
КонецПроцедуры

&НаКлиенте
Процедура КаталогOutputxUnitНачалоВыбораЗавершение(ВыбранныеФайлы, ТекущиеДанные) Экспорт
	Если Ложь
		Или ВыбранныеФайлы = Неопределено
		Или ВыбранныеФайлы.Количество() = 0
		Тогда
		
		Возврат;
	КонецЕсли;
	
	Объект.КаталогOutputxUnit = ВыбранныеФайлы[0];
КонецПроцедуры


&НаКлиенте
Процедура КаталогOutputИнструкцияHTMLНачалоВыбора(Элемент, ДанныеВыбора, СтандартнаяОбработка)
	СтандартнаяОбработка = Ложь;

	ДиалогВыбораКаталога = Новый ДиалогВыбораФайла(РежимДиалогаВыбораФайла.ВыборКаталога);
	
	ДиалогВыбораКаталога.МножественныйВыбор = Ложь;
	
	ДиалогВыбораКаталога.Показать(Вычислить("Новый ОписаниеОповещения(""КаталогOutputИнструкцияHTMLЗавершение"", ЭтотОбъект)"));
КонецПроцедуры

&НаКлиенте
Процедура КаталогOutputИнструкцияMarkdownНачалоВыбора(Элемент, ДанныеВыбора, СтандартнаяОбработка)
	СтандартнаяОбработка = Ложь;

	ДиалогВыбораКаталога = Новый ДиалогВыбораФайла(РежимДиалогаВыбораФайла.ВыборКаталога);
	
	ДиалогВыбораКаталога.МножественныйВыбор = Ложь;
	
	ДиалогВыбораКаталога.Показать(Вычислить("Новый ОписаниеОповещения(""КаталогOutputИнструкцияMarkdownЗавершение"", ЭтотОбъект)"));
КонецПроцедуры

&НаКлиенте
Процедура КаталогOutputИнструкцияHTMLЗавершение(ВыбранныеФайлы, ТекущиеДанные) Экспорт
	Если Ложь
		Или ВыбранныеФайлы = Неопределено
		Или ВыбранныеФайлы.Количество() = 0
		Тогда
		
		Возврат;
	КонецЕсли;
	
	Объект.КаталогOutputИнструкцияHTML = ВыбранныеФайлы[0];
КонецПроцедуры

&НаКлиенте
Процедура КаталогOutputИнструкцияMarkdownЗавершение(ВыбранныеФайлы, ТекущиеДанные) Экспорт
	Если Ложь
		Или ВыбранныеФайлы = Неопределено
		Или ВыбранныеФайлы.Количество() = 0
		Тогда
		
		Возврат;
	КонецЕсли;
	
	Объект.КаталогOutputИнструкцияMarkdown = ВыбранныеФайлы[0];
КонецПроцедуры


&НаКлиенте
Процедура КаталогOutputИнструкцияВидеоНачалоВыбора(Элемент, ДанныеВыбора, СтандартнаяОбработка)
	СтандартнаяОбработка = Ложь;

	ДиалогВыбораКаталога = Новый ДиалогВыбораФайла(РежимДиалогаВыбораФайла.ВыборКаталога);
	
	ДиалогВыбораКаталога.МножественныйВыбор = Ложь;
	
	ДиалогВыбораКаталога.Показать(Вычислить("Новый ОписаниеОповещения(""КаталогOutputИнструкцияВидеоЗавершение"", ЭтотОбъект)"));
КонецПроцедуры

&НаКлиенте
Процедура КаталогOutputИнструкцияВидеоЗавершение(ВыбранныеФайлы, ТекущиеДанные) Экспорт
	Если Ложь
		Или ВыбранныеФайлы = Неопределено
		Или ВыбранныеФайлы.Количество() = 0
		Тогда
		
		Возврат;
	КонецЕсли;
	
	Объект.КаталогOutputИнструкцияВидео = ВыбранныеФайлы[0];
КонецПроцедуры


&НаКлиенте
Процедура КаталогСкриптовСборкиВидеоНачалоВыбора(Элемент, ДанныеВыбора, СтандартнаяОбработка)
	СтандартнаяОбработка = Ложь;

	ДиалогВыбораКаталога = Новый ДиалогВыбораФайла(РежимДиалогаВыбораФайла.ВыборКаталога);
	
	ДиалогВыбораКаталога.МножественныйВыбор = Ложь;
	
	ДиалогВыбораКаталога.Показать(Вычислить("Новый ОписаниеОповещения(""КаталогСкриптовСборкиВидеоЗавершение"", ЭтотОбъект)"));
КонецПроцедуры

&НаКлиенте
Процедура КаталогСкриптовСборкиВидеоЗавершение(ВыбранныеФайлы, ТекущиеДанные) Экспорт
	Если Ложь
		Или ВыбранныеФайлы = Неопределено
		Или ВыбранныеФайлы.Количество() = 0
		Тогда
		
		Возврат;
	КонецЕсли;
	
	Объект.КаталогСкриптовСборкиВидео = ВыбранныеФайлы[0];
КонецПроцедуры


&НаКлиенте
Процедура VanessaStackCommonsНачалоВыбора(Элемент, ДанныеВыбора, СтандартнаяОбработка)
	СтандартнаяОбработка = Ложь;

	ДиалогВыбораКаталога = Новый ДиалогВыбораФайла(РежимДиалогаВыбораФайла.ВыборКаталога);
	
	ДиалогВыбораКаталога.МножественныйВыбор = Ложь;
	
	ДиалогВыбораКаталога.Показать(Вычислить("Новый ОписаниеОповещения(""VanessaStackCommonsЗавершение"", ЭтотОбъект)"));
КонецПроцедуры

&НаКлиенте
Процедура VanessaStackCommonsЗавершение(ВыбранныеФайлы, ТекущиеДанные) Экспорт
	Если Ложь
		Или ВыбранныеФайлы = Неопределено
		Или ВыбранныеФайлы.Количество() = 0
		Тогда
		
		Возврат;
	КонецЕсли;
	
	Объект.VanessaStackCommons = ВыбранныеФайлы[0];
КонецПроцедуры


&НаКлиенте
Процедура КаталогИнструментовНачалоВыбора(Элемент, ДанныеВыбора, СтандартнаяОбработка)
	СтандартнаяОбработка = Ложь;

	ДиалогВыбораКаталога = Новый ДиалогВыбораФайла(РежимДиалогаВыбораФайла.ВыборКаталога);
	
	ДиалогВыбораКаталога.МножественныйВыбор = Ложь;
	
	ДиалогВыбораКаталога.Показать(Вычислить("Новый ОписаниеОповещения(""КаталогИнструментовЗавершение"", ЭтотОбъект)"));
КонецПроцедуры

&НаКлиенте
Процедура КаталогИнструментовЗавершение(ВыбранныеФайлы, ТекущиеДанные) Экспорт
	Если Ложь
		Или ВыбранныеФайлы = Неопределено
		Или ВыбранныеФайлы.Количество() = 0
		Тогда
		
		Возврат;
	КонецЕсли;
	
	Объект.КаталогИнструментов = ВыбранныеФайлы[0];
КонецПроцедуры

&НаКлиенте
Процедура TASKKILL(ИмяПриложения)
	СтрокаКоманды = "TASKKILL /F /IM " + ИмяПриложения;
	ВыполнитьКомандуОСБезПоказаЧерногоОкна(СтрокаКоманды);	
КонецПроцедуры
//}выбор каталогов


&НаКлиенте
Функция ПолучитьМассивСнипетовПрерывающихЗаписьСценария()
	Массив = Новый Массив;
	Массив.Добавить("обратитевнимание");
	
	Возврат Массив;
КонецФункции	

//свёртка дерева до строк фич
&НаКлиенте
Процедура СвернутьДеревоДоФичРекурсивно(ДеревоФормыСтроки)
	Для Каждого Строка Из ДеревоФормыСтроки Цикл
		Если Строка.Фича = Истина Тогда
			СвернутьСтрокуДерева(Строка);
			Продолжить;
		КонецЕсли;	 
		
		ПодчиненныеСтроки = Строка.ПолучитьЭлементы();
		Если ПодчиненныеСтроки.Количество() > 0 Тогда
			СвернутьДеревоДоФичРекурсивно(ПодчиненныеСтроки);
		КонецЕсли;	 
	КонецЦикла;
КонецПроцедуры

&НаКлиенте
Процедура СвернутьДеревоДоФич(Команда)
	ДеревоФормыСтроки = Объект.ДеревоТестов.ПолучитьЭлементы();
	СвернутьДеревоДоФичРекурсивно(ДеревоФормыСтроки);
КонецПроцедуры

//свёртка дерева до строк сценариев
&НаКлиенте
Процедура СвернутьДеревоДоСценариевРекурсивно(ДеревоФормыСтроки)
	Для Каждого Строка Из ДеревоФормыСтроки Цикл
		Если Строка.Фича = Истина Тогда
			РазвернутьСтрокуДерева(Строка);
		КонецЕсли;	 
		
		Если Строка.Сценарий = Истина Тогда
			СвернутьСтрокуДерева(Строка);
			Продолжить;
		КонецЕсли;	 
		
		ПодчиненныеСтроки = Строка.ПолучитьЭлементы();
		Если ПодчиненныеСтроки.Количество() > 0 Тогда
			СвернутьДеревоДоСценариевРекурсивно(ПодчиненныеСтроки);
		КонецЕсли;	 
	КонецЦикла;
КонецПроцедуры

&НаКлиенте
Процедура СвернутьДеревоДоСценариев(Команда)
	ДеревоФормыСтроки = Объект.ДеревоТестов.ПолучитьЭлементы();
	СвернутьДеревоДоСценариевРекурсивно(ДеревоФормыСтроки);
КонецПроцедуры


ТаблицаОбработокДляОтладки = Новый Соответствие;

ВыполнятьСценарииАсинхронно = Истина;

ШагСтрокДляМодуля         = 10000;
ВсёЕщёИдётВыполнениеШагов = 0;

МассивСостоянияКонтекстовДоВыполненияШага = Новый Массив;

ТаблицаУжеСуществующихСценариев = Новый Массив();


МассивВерсийFeatureИмяФайла = Новый Массив;
МассивВерсийFeatureВерсия   = Новый Массив;

МассивВерсийEPFИмяФайла = Новый Массив;
МассивВерсийEPFВерсия   = Новый Массив;

ТаблицаКонтекстовОбработок = Новый Массив;
МассивИменКонтекстовОбработок = Новый Массив;

ЭтоLinux = Ложь;


СчитываниеМакетаНачСтр = 1;
СчитываниеМакетаНачКол = 1;
СчитываниеМакетаКолСтр = 30;
СчитываниеМакетаКолКол = 30;

ПрекратитьВыполнениШаговТакКакЗакончилсяСценарий = Ложь;
ИнтервалВыполненияШагаПриЗаписиВидео             = 4;
БылаОшибкаСкриптовСборкиВидео                    = Ложь;
СкриншотСделанВСценарии                          = Ложь;
ЭтоЗапускВРежимеКоманднойСтроки                  = Ложь;
ЭтоЗапускВРежимеБезЗагрукиНастроек               = Ложь;

МассивTTS = Неопределено;

ПредставлениеВертЧертыВТабДок = "__&ВертЧерта__";